Annotation of gcc/config/m68k/lb1sf68.asm, revision 1.1.1.1

1.1       root        1: /* libgcc1 routines for 68000 w/o floating-point hardware. */
                      2: /* Copyright (C) 1994 Free Software Foundation, Inc.
                      3: 
                      4: This file is free software; you can redistribute it and/or modify it
                      5: under the terms of the GNU General Public License as published by the
                      6: Free Software Foundation; either version 2, or (at your option) any
                      7: later version.
                      8: 
                      9: In addition to the permissions in the GNU General Public License, the
                     10: Free Software Foundation gives you unlimited permission to link the
                     11: compiled version of this file with other programs, and to distribute
                     12: those programs without any restriction coming from the use of this
                     13: file.  (The General Public License restrictions do apply in other
                     14: respects; for example, they cover modification of the file, and
                     15: distribution when not linked into another program.)
                     16: 
                     17: This file is distributed in the hope that it will be useful, but
                     18: WITHOUT ANY WARRANTY; without even the implied warranty of
                     19: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     20: General Public License for more details.
                     21: 
                     22: You should have received a copy of the GNU General Public License
                     23: along with this program; see the file COPYING.  If not, write to
                     24: the Free Software Foundation, 59 Temple Place - Suite 330,
                     25: Boston, MA 02111-1307, USA.  */
                     26: 
                     27: /* As a special exception, if you link this library with files
                     28:    compiled with GCC to produce an executable, this does not cause
                     29:    the resulting executable to be covered by the GNU General Public License.
                     30:    This exception does not however invalidate any other reasons why
                     31:    the executable file might be covered by the GNU General Public License.  */
                     32: 
                     33: /* Use this one for any 680x0; assumes no floating point hardware.
                     34:    The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
                     35:    Some of this code comes from MINIX, via the folks at ericsson.
                     36:    D. V. Henkel-Wallace ([email protected]) Fete Bastille, 1992
                     37: */
                     38: 
                     39: /* These are predefined by new versions of GNU cpp.  */
                     40: 
                     41: #ifndef __USER_LABEL_PREFIX__
                     42: #define __USER_LABEL_PREFIX__ _
                     43: #endif
                     44: 
                     45: #ifndef __REGISTER_PREFIX__
                     46: #define __REGISTER_PREFIX__
                     47: #endif
                     48: 
                     49: #ifndef __IMMEDIATE_PREFIX__
                     50: #define __IMMEDIATE_PREFIX__ #
                     51: #endif
                     52: 
                     53: /* ANSI concatenation macros.  */
                     54: 
                     55: #define CONCAT1(a, b) CONCAT2(a, b)
                     56: #define CONCAT2(a, b) a ## b
                     57: 
                     58: /* Use the right prefix for global labels.  */
                     59: 
                     60: #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
                     61: 
                     62: /* Use the right prefix for registers.  */
                     63: 
                     64: #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
                     65: 
                     66: /* Use the right prefix for immediate values.  */
                     67: 
                     68: #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
                     69: 
                     70: #define d0 REG (d0)
                     71: #define d1 REG (d1)
                     72: #define d2 REG (d2)
                     73: #define d3 REG (d3)
                     74: #define d4 REG (d4)
                     75: #define d5 REG (d5)
                     76: #define d6 REG (d6)
                     77: #define d7 REG (d7)
                     78: #define a0 REG (a0)
                     79: #define a1 REG (a1)
                     80: #define a2 REG (a2)
                     81: #define a3 REG (a3)
                     82: #define a4 REG (a4)
                     83: #define a5 REG (a5)
                     84: #define a6 REG (a6)
                     85: #define fp REG (fp)
                     86: #define sp REG (sp)
                     87: 
                     88: #ifdef L_floatex
                     89: 
                     90: | This is an attempt at a decent floating point (single, double and 
                     91: | extended double) code for the GNU C compiler. It should be easy to
                     92: | adapt to other compilers (but beware of the local labels!).
                     93: 
                     94: | Starting date: 21 October, 1990
                     95: 
                     96: | It is convenient to introduce the notation (s,e,f) for a floating point
                     97: | number, where s=sign, e=exponent, f=fraction. We will call a floating
                     98: | point number fpn to abbreviate, independently of the precision.
                     99: | Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023 
                    100: | for doubles and 16383 for long doubles). We then have the following 
                    101: | different cases:
                    102: |  1. Normalized fpns have 0 < e < MAX_EXP. They correspond to 
                    103: |     (-1)^s x 1.f x 2^(e-bias-1).
                    104: |  2. Denormalized fpns have e=0. They correspond to numbers of the form
                    105: |     (-1)^s x 0.f x 2^(-bias).
                    106: |  3. +/-INFINITY have e=MAX_EXP, f=0.
                    107: |  4. Quiet NaN (Not a Number) have all bits set.
                    108: |  5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1.
                    109: 
                    110: |=============================================================================
                    111: |                                  exceptions
                    112: |=============================================================================
                    113: 
                    114: | This is the floating point condition code register (_fpCCR):
                    115: |
                    116: | struct {
                    117: |   short _exception_bits;     
                    118: |   short _trap_enable_bits;   
                    119: |   short _sticky_bits;
                    120: |   short _rounding_mode;
                    121: |   short _format;
                    122: |   short _last_operation;
                    123: |   union {
                    124: |     float sf;
                    125: |     double df;
                    126: |   } _operand1;
                    127: |   union {
                    128: |     float sf;
                    129: |     double df;
                    130: |   } _operand2;
                    131: | } _fpCCR;
                    132: 
                    133:        .data
                    134:        .even
                    135: 
                    136:        .globl  SYM (_fpCCR)
                    137:        
                    138: SYM (_fpCCR):
                    139: __exception_bits:
                    140:        .word   0
                    141: __trap_enable_bits:
                    142:        .word   0
                    143: __sticky_bits:
                    144:        .word   0
                    145: __rounding_mode:
                    146:        .word   ROUND_TO_NEAREST
                    147: __format:
                    148:        .word   NIL
                    149: __last_operation:
                    150:        .word   NOOP
                    151: __operand1:
                    152:        .long   0
                    153:        .long   0
                    154: __operand2:
                    155:        .long   0
                    156:        .long   0
                    157: 
                    158: | Offsets:
                    159: EBITS  = __exception_bits - SYM (_fpCCR)
                    160: TRAPE  = __trap_enable_bits - SYM (_fpCCR)
                    161: STICK  = __sticky_bits - SYM (_fpCCR)
                    162: ROUND  = __rounding_mode - SYM (_fpCCR)
                    163: FORMT  = __format - SYM (_fpCCR)
                    164: LASTO  = __last_operation - SYM (_fpCCR)
                    165: OPER1  = __operand1 - SYM (_fpCCR)
                    166: OPER2  = __operand2 - SYM (_fpCCR)
                    167: 
                    168: | The following exception types are supported:
                    169: INEXACT_RESULT                 = 0x0001
                    170: UNDERFLOW              = 0x0002
                    171: OVERFLOW               = 0x0004
                    172: DIVIDE_BY_ZERO                 = 0x0008
                    173: INVALID_OPERATION      = 0x0010
                    174: 
                    175: | The allowed rounding modes are:
                    176: UNKNOWN           = -1
                    177: ROUND_TO_NEAREST  = 0 | round result to nearest representable value
                    178: ROUND_TO_ZERO     = 1 | round result towards zero
                    179: ROUND_TO_PLUS     = 2 | round result towards plus infinity
                    180: ROUND_TO_MINUS    = 3 | round result towards minus infinity
                    181: 
                    182: | The allowed values of format are:
                    183: NIL          = 0
                    184: SINGLE_FLOAT = 1
                    185: DOUBLE_FLOAT = 2
                    186: LONG_FLOAT   = 3
                    187: 
                    188: | The allowed values for the last operation are:
                    189: NOOP         = 0
                    190: ADD          = 1
                    191: MULTIPLY     = 2
                    192: DIVIDE       = 3
                    193: NEGATE       = 4
                    194: COMPARE      = 5
                    195: EXTENDSFDF   = 6
                    196: TRUNCDFSF    = 7
                    197: 
                    198: |=============================================================================
                    199: |                           __clear_sticky_bits
                    200: |=============================================================================
                    201: 
                    202: | The sticky bits are normally not cleared (thus the name), whereas the 
                    203: | exception type and exception value reflect the last computation. 
                    204: | This routine is provided to clear them (you can also write to _fpCCR,
                    205: | since it is globally visible).
                    206: 
                    207:        .globl  SYM (__clear_sticky_bit)
                    208: 
                    209:        .text
                    210:        .even
                    211: 
                    212: | void __clear_sticky_bits(void);
                    213: SYM (__clear_sticky_bit):              
                    214:        lea     SYM (_fpCCR),a0
                    215:        movew   IMM (0),a0@(STICK)
                    216:        rts
                    217: 
                    218: |=============================================================================
                    219: |                           $_exception_handler
                    220: |=============================================================================
                    221: 
                    222:        .globl  $_exception_handler
                    223: 
                    224:        .text
                    225:        .even
                    226: 
                    227: | This is the common exit point if an exception occurs.
                    228: | NOTE: it is NOT callable from C!
                    229: | It expects the exception type in d7, the format (SINGLE_FLOAT,
                    230: | DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5.
                    231: | It sets the corresponding exception and sticky bits, and the format. 
                    232: | Depending on the format if fills the corresponding slots for the 
                    233: | operands which produced the exception (all this information is provided
                    234: | so if you write your own exception handlers you have enough information
                    235: | to deal with the problem).
                    236: | Then checks to see if the corresponding exception is trap-enabled, 
                    237: | in which case it pushes the address of _fpCCR and traps through 
                    238: | trap FPTRAP (15 for the moment).
                    239: 
                    240: FPTRAP = 15
                    241: 
                    242: $_exception_handler:
                    243:        lea     SYM (_fpCCR),a0
                    244:        movew   d7,a0@(EBITS)   | set __exception_bits
                    245:        orw     d7,a0@(STICK)   | and __sticky_bits
                    246:        movew   d6,a0@(FORMT)   | and __format
                    247:        movew   d5,a0@(LASTO)   | and __last_operation
                    248: 
                    249: | Now put the operands in place:
                    250:        cmpw    IMM (SINGLE_FLOAT),d6
                    251:        beq     1f
                    252:        movel   a6@(8),a0@(OPER1)
                    253:        movel   a6@(12),a0@(OPER1+4)
                    254:        movel   a6@(16),a0@(OPER2)
                    255:        movel   a6@(20),a0@(OPER2+4)
                    256:        bra     2f
                    257: 1:     movel   a6@(8),a0@(OPER1)
                    258:        movel   a6@(12),a0@(OPER2)
                    259: 2:
                    260: | And check whether the exception is trap-enabled:
                    261:        andw    a0@(TRAPE),d7   | is exception trap-enabled?
                    262:        beq     1f              | no, exit
                    263:        pea     SYM (_fpCCR)    | yes, push address of _fpCCR
                    264:        trap    IMM (FPTRAP)    | and trap
                    265: 1:     moveml  sp@+,d2-d7      | restore data registers
                    266:        unlk    a6              | and return
                    267:        rts
                    268: #endif /* L_floatex */
                    269: 
                    270: #ifdef  L_mulsi3
                    271:        .text
                    272:        .proc
                    273:        .globl  SYM (__mulsi3)
                    274: SYM (__mulsi3):
                    275:        movew   sp@(4), d0      /* x0 -> d0 */
                    276:        muluw   sp@(10), d0     /* x0*y1 */
                    277:        movew   sp@(6), d1      /* x1 -> d1 */
                    278:        muluw   sp@(8), d1      /* x1*y0 */
                    279:        addw    d1, d0
                    280:        swap    d0
                    281:        clrw    d0
                    282:        movew   sp@(6), d1      /* x1 -> d1 */
                    283:        muluw   sp@(10), d1     /* x1*y1 */
                    284:        addl    d1, d0
                    285: 
                    286:        rts
                    287: #endif /* L_mulsi3 */
                    288: 
                    289: #ifdef  L_udivsi3
                    290:        .text
                    291:        .proc
                    292:        .globl  SYM (__udivsi3)
                    293: SYM (__udivsi3):
                    294:        movel   d2, sp@-
                    295:        movel   sp@(12), d1     /* d1 = divisor */
                    296:        movel   sp@(8), d0      /* d0 = dividend */
                    297: 
                    298:        cmpl    IMM (0x10000), d1 /* divisor >= 2 ^ 16 ?   */
                    299:        jcc     L3              /* then try next algorithm */
                    300:        movel   d0, d2
                    301:        clrw    d2
                    302:        swap    d2
                    303:        divu    d1, d2          /* high quotient in lower word */
                    304:        movew   d2, d0          /* save high quotient */
                    305:        swap    d0
                    306:        movew   sp@(10), d2     /* get low dividend + high rest */
                    307:        divu    d1, d2          /* low quotient */
                    308:        movew   d2, d0
                    309:        jra     L6
                    310: 
                    311: L3:    movel   d1, d2          /* use d2 as divisor backup */
                    312: L4:    lsrl    IMM (1), d1     /* shift divisor */
                    313:        lsrl    IMM (1), d0     /* shift dividend */
                    314:        cmpl    IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ?  */
                    315:        jcc     L4
                    316:        divu    d1, d0          /* now we have 16 bit divisor */
                    317:        andl    IMM (0xffff), d0 /* mask out divisor, ignore remainder */
                    318: 
                    319: /* Multiply the 16 bit tentative quotient with the 32 bit divisor.  Because of
                    320:    the operand ranges, this might give a 33 bit product.  If this product is
                    321:    greater than the dividend, the tentative quotient was too large. */
                    322:        movel   d2, d1
                    323:        mulu    d0, d1          /* low part, 32 bits */
                    324:        swap    d2
                    325:        mulu    d0, d2          /* high part, at most 17 bits */
                    326:        swap    d2              /* align high part with low part */
                    327:        btst    IMM (0), d2     /* high part 17 bits? */
                    328:        jne     L5              /* if 17 bits, quotient was too large */
                    329:        addl    d2, d1          /* add parts */
                    330:        jcs     L5              /* if sum is 33 bits, quotient was too large */
                    331:        cmpl    sp@(8), d1      /* compare the sum with the dividend */
                    332:        jls     L6              /* if sum > dividend, quotient was too large */
                    333: L5:    subql   IMM (1), d0     /* adjust quotient */
                    334: 
                    335: L6:    movel   sp@+, d2
                    336:        rts
                    337: #endif /* L_udivsi3 */
                    338: 
                    339: #ifdef  L_divsi3
                    340:        .text
                    341:        .proc
                    342:        .globl  SYM (__divsi3)
                    343: SYM (__divsi3):
                    344:        movel   d2, sp@-
                    345: 
                    346:        moveb   IMM (1), d2     /* sign of result stored in d2 (=1 or =-1) */
                    347:        movel   sp@(12), d1     /* d1 = divisor */
                    348:        jpl     L1
                    349:        negl    d1
                    350:        negb    d2              /* change sign because divisor <0  */
                    351: L1:    movel   sp@(8), d0      /* d0 = dividend */
                    352:        jpl     L2
                    353:        negl    d0
                    354:        negb    d2
                    355: 
                    356: L2:    movel   d1, sp@-
                    357:        movel   d0, sp@-
                    358:        jbsr    SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */
                    359:        addql   IMM (8), sp
                    360: 
                    361:        tstb    d2
                    362:        jpl     L3
                    363:        negl    d0
                    364: 
                    365: L3:    movel   sp@+, d2
                    366:        rts
                    367: #endif /* L_divsi3 */
                    368: 
                    369: #ifdef  L_umodsi3
                    370:        .text
                    371:        .proc
                    372:        .globl  SYM (__umodsi3)
                    373: SYM (__umodsi3):
                    374:        movel   sp@(8), d1      /* d1 = divisor */
                    375:        movel   sp@(4), d0      /* d0 = dividend */
                    376:        movel   d1, sp@-
                    377:        movel   d0, sp@-
                    378:        jbsr    SYM (__udivsi3)
                    379:        addql   IMM (8), sp
                    380:        movel   sp@(8), d1      /* d1 = divisor */
                    381:        movel   d1, sp@-
                    382:        movel   d0, sp@-
                    383:        jbsr    SYM (__mulsi3)  /* d0 = (a/b)*b */
                    384:        addql   IMM (8), sp
                    385:        movel   sp@(4), d1      /* d1 = dividend */
                    386:        subl    d0, d1          /* d1 = a - (a/b)*b */
                    387:        movel   d1, d0
                    388:        rts
                    389: #endif /* L_umodsi3 */
                    390: 
                    391: #ifdef  L_modsi3
                    392:        .text
                    393:        .proc
                    394:        .globl  SYM (__modsi3)
                    395: SYM (__modsi3):
                    396:        movel   sp@(8), d1      /* d1 = divisor */
                    397:        movel   sp@(4), d0      /* d0 = dividend */
                    398:        movel   d1, sp@-
                    399:        movel   d0, sp@-
                    400:        jbsr    SYM (__divsi3)
                    401:        addql   IMM (8), sp
                    402:        movel   sp@(8), d1      /* d1 = divisor */
                    403:        movel   d1, sp@-
                    404:        movel   d0, sp@-
                    405:        jbsr    SYM (__mulsi3)  /* d0 = (a/b)*b */
                    406:        addql   IMM (8), sp
                    407:        movel   sp@(4), d1      /* d1 = dividend */
                    408:        subl    d0, d1          /* d1 = a - (a/b)*b */
                    409:        movel   d1, d0
                    410:        rts
                    411: #endif /* L_modsi3 */
                    412: 
                    413: 
                    414: #ifdef  L_double
                    415: 
                    416:        .globl  SYM (_fpCCR)
                    417:        .globl  $_exception_handler
                    418: 
                    419: QUIET_NaN      = 0xffffffff
                    420: 
                    421: D_MAX_EXP      = 0x07ff
                    422: D_BIAS         = 1022
                    423: DBL_MAX_EXP    = D_MAX_EXP - D_BIAS
                    424: DBL_MIN_EXP    = 1 - D_BIAS
                    425: DBL_MANT_DIG   = 53
                    426: 
                    427: INEXACT_RESULT                 = 0x0001
                    428: UNDERFLOW              = 0x0002
                    429: OVERFLOW               = 0x0004
                    430: DIVIDE_BY_ZERO                 = 0x0008
                    431: INVALID_OPERATION      = 0x0010
                    432: 
                    433: DOUBLE_FLOAT = 2
                    434: 
                    435: NOOP         = 0
                    436: ADD          = 1
                    437: MULTIPLY     = 2
                    438: DIVIDE       = 3
                    439: NEGATE       = 4
                    440: COMPARE      = 5
                    441: EXTENDSFDF   = 6
                    442: TRUNCDFSF    = 7
                    443: 
                    444: UNKNOWN           = -1
                    445: ROUND_TO_NEAREST  = 0 | round result to nearest representable value
                    446: ROUND_TO_ZERO     = 1 | round result towards zero
                    447: ROUND_TO_PLUS     = 2 | round result towards plus infinity
                    448: ROUND_TO_MINUS    = 3 | round result towards minus infinity
                    449: 
                    450: | Entry points:
                    451: 
                    452:        .globl SYM (__adddf3)
                    453:        .globl SYM (__subdf3)
                    454:        .globl SYM (__muldf3)
                    455:        .globl SYM (__divdf3)
                    456:        .globl SYM (__negdf2)
                    457:        .globl SYM (__cmpdf2)
                    458: 
                    459:        .text
                    460:        .even
                    461: 
                    462: | These are common routines to return and signal exceptions.   
                    463: 
                    464: Ld$den:
                    465: | Return and signal a denormalized number
                    466:        orl     d7,d0
                    467:        movew   IMM (UNDERFLOW),d7
                    468:        orw     IMM (INEXACT_RESULT),d7
                    469:        movew   IMM (DOUBLE_FLOAT),d6
                    470:        jmp     $_exception_handler
                    471: 
                    472: Ld$infty:
                    473: Ld$overflow:
                    474: | Return a properly signed INFINITY and set the exception flags 
                    475:        movel   IMM (0x7ff00000),d0
                    476:        movel   IMM (0),d1
                    477:        orl     d7,d0
                    478:        movew   IMM (OVERFLOW),d7
                    479:        orw     IMM (INEXACT_RESULT),d7
                    480:        movew   IMM (DOUBLE_FLOAT),d6
                    481:        jmp     $_exception_handler
                    482: 
                    483: Ld$underflow:
                    484: | Return 0 and set the exception flags 
                    485:        movel   IMM (0),d0
                    486:        movel   d0,d1
                    487:        movew   IMM (UNDERFLOW),d7
                    488:        orw     IMM (INEXACT_RESULT),d7
                    489:        movew   IMM (DOUBLE_FLOAT),d6
                    490:        jmp     $_exception_handler
                    491: 
                    492: Ld$inop:
                    493: | Return a quiet NaN and set the exception flags
                    494:        movel   IMM (QUIET_NaN),d0
                    495:        movel   d0,d1
                    496:        movew   IMM (INVALID_OPERATION),d7
                    497:        orw     IMM (INEXACT_RESULT),d7
                    498:        movew   IMM (DOUBLE_FLOAT),d6
                    499:        jmp     $_exception_handler
                    500: 
                    501: Ld$div$0:
                    502: | Return a properly signed INFINITY and set the exception flags
                    503:        movel   IMM (0x7ff00000),d0
                    504:        movel   IMM (0),d1
                    505:        orl     d7,d0
                    506:        movew   IMM (DIVIDE_BY_ZERO),d7
                    507:        orw     IMM (INEXACT_RESULT),d7
                    508:        movew   IMM (DOUBLE_FLOAT),d6
                    509:        jmp     $_exception_handler
                    510: 
                    511: |=============================================================================
                    512: |=============================================================================
                    513: |                         double precision routines
                    514: |=============================================================================
                    515: |=============================================================================
                    516: 
                    517: | A double precision floating point number (double) has the format:
                    518: |
                    519: | struct _double {
                    520: |  unsigned int sign      : 1;  /* sign bit */ 
                    521: |  unsigned int exponent  : 11; /* exponent, shifted by 126 */
                    522: |  unsigned int fraction  : 52; /* fraction */
                    523: | } double;
                    524: | 
                    525: | Thus sizeof(double) = 8 (64 bits). 
                    526: |
                    527: | All the routines are callable from C programs, and return the result 
                    528: | in the register pair d0-d1. They also preserve all registers except 
                    529: | d0-d1 and a0-a1.
                    530: 
                    531: |=============================================================================
                    532: |                              __subdf3
                    533: |=============================================================================
                    534: 
                    535: | double __subdf3(double, double);
                    536: SYM (__subdf3):
                    537:        bchg    IMM (31),sp@(12) | change sign of second operand
                    538:                                | and fall through, so we always add
                    539: |=============================================================================
                    540: |                              __adddf3
                    541: |=============================================================================
                    542: 
                    543: | double __adddf3(double, double);
                    544: SYM (__adddf3):
                    545:        link    a6,IMM (0)      | everything will be done in registers
                    546:        moveml  d2-d7,sp@-      | save all data registers and a2 (but d0-d1)
                    547:        movel   a6@(8),d0       | get first operand
                    548:        movel   a6@(12),d1      | 
                    549:        movel   a6@(16),d2      | get second operand
                    550:        movel   a6@(20),d3      | 
                    551: 
                    552:        movel   d0,d7           | get d0's sign bit in d7 '
                    553:        addl    d1,d1           | check and clear sign bit of a, and gain one
                    554:        addxl   d0,d0           | bit of extra precision
                    555:        beq     Ladddf$b        | if zero return second operand
                    556: 
                    557:        movel   d2,d6           | save sign in d6 
                    558:        addl    d3,d3           | get rid of sign bit and gain one bit of
                    559:        addxl   d2,d2           | extra precision
                    560:        beq     Ladddf$a        | if zero return first operand
                    561: 
                    562:        andl    IMM (0x80000000),d7 | isolate a's sign bit '
                    563:         swap   d6              | and also b's sign bit '
                    564:        andw    IMM (0x8000),d6 |
                    565:        orw     d6,d7           | and combine them into d7, so that a's sign '
                    566:                                | bit is in the high word and b's is in the '
                    567:                                | low word, so d6 is free to be used
                    568:        movel   d7,a0           | now save d7 into a0, so d7 is free to
                    569:                                | be used also
                    570: 
                    571: | Get the exponents and check for denormalized and/or infinity.
                    572: 
                    573:        movel   IMM (0x001fffff),d6 | mask for the fraction
                    574:        movel   IMM (0x00200000),d7 | mask to put hidden bit back
                    575: 
                    576:        movel   d0,d4           | 
                    577:        andl    d6,d0           | get fraction in d0
                    578:        notl    d6              | make d6 into mask for the exponent
                    579:        andl    d6,d4           | get exponent in d4
                    580:        beq     Ladddf$a$den    | branch if a is denormalized
                    581:        cmpl    d6,d4           | check for INFINITY or NaN
                    582:        beq     Ladddf$nf       | 
                    583:        orl     d7,d0           | and put hidden bit back
                    584: Ladddf$1:
                    585:        swap    d4              | shift right exponent so that it starts
                    586:        lsrw    IMM (5),d4      | in bit 0 and not bit 20
                    587: | Now we have a's exponent in d4 and fraction in d0-d1 '
                    588:        movel   d2,d5           | save b to get exponent
                    589:        andl    d6,d5           | get exponent in d5
                    590:        beq     Ladddf$b$den    | branch if b is denormalized
                    591:        cmpl    d6,d5           | check for INFINITY or NaN
                    592:        beq     Ladddf$nf
                    593:        notl    d6              | make d6 into mask for the fraction again
                    594:        andl    d6,d2           | and get fraction in d2
                    595:        orl     d7,d2           | and put hidden bit back
                    596: Ladddf$2:
                    597:        swap    d5              | shift right exponent so that it starts
                    598:        lsrw    IMM (5),d5      | in bit 0 and not bit 20
                    599: 
                    600: | Now we have b's exponent in d5 and fraction in d2-d3. '
                    601: 
                    602: | The situation now is as follows: the signs are combined in a0, the 
                    603: | numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a)
                    604: | and d5 (b). To do the rounding correctly we need to keep all the
                    605: | bits until the end, so we need to use d0-d1-d2-d3 for the first number
                    606: | and d4-d5-d6-d7 for the second. To do this we store (temporarily) the
                    607: | exponents in a2-a3.
                    608: 
                    609:        moveml  a2-a3,sp@-      | save the address registers
                    610: 
                    611:        movel   d4,a2           | save the exponents
                    612:        movel   d5,a3           | 
                    613: 
                    614:        movel   IMM (0),d7      | and move the numbers around
                    615:        movel   d7,d6           |
                    616:        movel   d3,d5           |
                    617:        movel   d2,d4           |
                    618:        movel   d7,d3           |
                    619:        movel   d7,d2           |
                    620: 
                    621: | Here we shift the numbers until the exponents are the same, and put 
                    622: | the largest exponent in a2.
                    623:        exg     d4,a2           | get exponents back
                    624:        exg     d5,a3           |
                    625:        cmpw    d4,d5           | compare the exponents
                    626:        beq     Ladddf$3        | if equal don't shift '
                    627:        bhi     9f              | branch if second exponent is higher
                    628: 
                    629: | Here we have a's exponent larger than b's, so we have to shift b. We do 
                    630: | this by using as counter d2:
                    631: 1:     movew   d4,d2           | move largest exponent to d2
                    632:        subw    d5,d2           | and subtract second exponent
                    633:        exg     d4,a2           | get back the longs we saved
                    634:        exg     d5,a3           |
                    635: | if difference is too large we don't shift (actually, we can just exit) '
                    636:        cmpw    IMM (DBL_MANT_DIG+2),d2
                    637:        bge     Ladddf$b$small
                    638:        cmpw    IMM (32),d2     | if difference >= 32, shift by longs
                    639:        bge     5f
                    640: 2:     cmpw    IMM (16),d2     | if difference >= 16, shift by words   
                    641:        bge     6f
                    642:        bra     3f              | enter dbra loop
                    643: 
                    644: 4:     lsrl    IMM (1),d4
                    645:        roxrl   IMM (1),d5
                    646:        roxrl   IMM (1),d6
                    647:        roxrl   IMM (1),d7
                    648: 3:     dbra    d2,4b
                    649:        movel   IMM (0),d2
                    650:        movel   d2,d3   
                    651:        bra     Ladddf$4
                    652: 5:
                    653:        movel   d6,d7
                    654:        movel   d5,d6
                    655:        movel   d4,d5
                    656:        movel   IMM (0),d4
                    657:        subw    IMM (32),d2
                    658:        bra     2b
                    659: 6:
                    660:        movew   d6,d7
                    661:        swap    d7
                    662:        movew   d5,d6
                    663:        swap    d6
                    664:        movew   d4,d5
                    665:        swap    d5
                    666:        movew   IMM (0),d4
                    667:        swap    d4
                    668:        subw    IMM (16),d2
                    669:        bra     3b
                    670:        
                    671: 9:     exg     d4,d5
                    672:        movew   d4,d6
                    673:        subw    d5,d6           | keep d5 (largest exponent) in d4
                    674:        exg     d4,a2
                    675:        exg     d5,a3
                    676: | if difference is too large we don't shift (actually, we can just exit) '
                    677:        cmpw    IMM (DBL_MANT_DIG+2),d6
                    678:        bge     Ladddf$a$small
                    679:        cmpw    IMM (32),d6     | if difference >= 32, shift by longs
                    680:        bge     5f
                    681: 2:     cmpw    IMM (16),d6     | if difference >= 16, shift by words   
                    682:        bge     6f
                    683:        bra     3f              | enter dbra loop
                    684: 
                    685: 4:     lsrl    IMM (1),d0
                    686:        roxrl   IMM (1),d1
                    687:        roxrl   IMM (1),d2
                    688:        roxrl   IMM (1),d3
                    689: 3:     dbra    d6,4b
                    690:        movel   IMM (0),d7
                    691:        movel   d7,d6
                    692:        bra     Ladddf$4
                    693: 5:
                    694:        movel   d2,d3
                    695:        movel   d1,d2
                    696:        movel   d0,d1
                    697:        movel   IMM (0),d0
                    698:        subw    IMM (32),d6
                    699:        bra     2b
                    700: 6:
                    701:        movew   d2,d3
                    702:        swap    d3
                    703:        movew   d1,d2
                    704:        swap    d2
                    705:        movew   d0,d1
                    706:        swap    d1
                    707:        movew   IMM (0),d0
                    708:        swap    d0
                    709:        subw    IMM (16),d6
                    710:        bra     3b
                    711: Ladddf$3:
                    712:        exg     d4,a2   
                    713:        exg     d5,a3
                    714: Ladddf$4:      
                    715: | Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and
                    716: | the signs in a4.
                    717: 
                    718: | Here we have to decide whether to add or subtract the numbers:
                    719:        exg     d7,a0           | get the signs 
                    720:        exg     d6,a3           | a3 is free to be used
                    721:        movel   d7,d6           |
                    722:        movew   IMM (0),d7      | get a's sign in d7 '
                    723:        swap    d6              |
                    724:        movew   IMM (0),d6      | and b's sign in d6 '
                    725:        eorl    d7,d6           | compare the signs
                    726:        bmi     Lsubdf$0        | if the signs are different we have 
                    727:                                | to subtract
                    728:        exg     d7,a0           | else we add the numbers
                    729:        exg     d6,a3           |
                    730:        addl    d7,d3           |
                    731:        addxl   d6,d2           |
                    732:        addxl   d5,d1           | 
                    733:        addxl   d4,d0           |
                    734: 
                    735:        movel   a2,d4           | return exponent to d4
                    736:        movel   a0,d7           | 
                    737:        andl    IMM (0x80000000),d7 | d7 now has the sign
                    738: 
                    739:        moveml  sp@+,a2-a3      
                    740: 
                    741: | Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
                    742: | the case of denormalized numbers in the rounding routine itself).
                    743: | As in the addition (not in the subtraction!) we could have set 
                    744: | one more bit we check this:
                    745:        btst    IMM (DBL_MANT_DIG+1),d0 
                    746:        beq     1f
                    747:        lsrl    IMM (1),d0
                    748:        roxrl   IMM (1),d1
                    749:        roxrl   IMM (1),d2
                    750:        roxrl   IMM (1),d3
                    751:        addw    IMM (1),d4
                    752: 1:
                    753:        lea     Ladddf$5,a0     | to return from rounding routine
                    754:        lea     SYM (_fpCCR),a1 | check the rounding mode
                    755:        movew   a1@(6),d6       | rounding mode in d6
                    756:        beq     Lround$to$nearest
                    757:        cmpw    IMM (ROUND_TO_PLUS),d6
                    758:        bhi     Lround$to$minus
                    759:        blt     Lround$to$zero
                    760:        bra     Lround$to$plus
                    761: Ladddf$5:
                    762: | Put back the exponent and check for overflow
                    763:        cmpw    IMM (0x7ff),d4  | is the exponent big?
                    764:        bge     1f
                    765:        bclr    IMM (DBL_MANT_DIG-1),d0
                    766:        lslw    IMM (4),d4      | put exponent back into position
                    767:        swap    d0              | 
                    768:        orw     d4,d0           |
                    769:        swap    d0              |
                    770:        bra     Ladddf$ret
                    771: 1:
                    772:        movew   IMM (ADD),d5
                    773:        bra     Ld$overflow
                    774: 
                    775: Lsubdf$0:
                    776: | Here we do the subtraction.
                    777:        exg     d7,a0           | put sign back in a0
                    778:        exg     d6,a3           |
                    779:        subl    d7,d3           |
                    780:        subxl   d6,d2           |
                    781:        subxl   d5,d1           |
                    782:        subxl   d4,d0           |
                    783:        beq     Ladddf$ret$1    | if zero just exit
                    784:        bpl     1f              | if positive skip the following
                    785:        exg     d7,a0           |
                    786:        bchg    IMM (31),d7     | change sign bit in d7
                    787:        exg     d7,a0           |
                    788:        negl    d3              |
                    789:        negxl   d2              |
                    790:        negxl   d1              | and negate result
                    791:        negxl   d0              |
                    792: 1:     
                    793:        movel   a2,d4           | return exponent to d4
                    794:        movel   a0,d7
                    795:        andl    IMM (0x80000000),d7 | isolate sign bit
                    796:        moveml  sp@+,a2-a3      |
                    797: 
                    798: | Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
                    799: | the case of denormalized numbers in the rounding routine itself).
                    800: | As in the addition (not in the subtraction!) we could have set 
                    801: | one more bit we check this:
                    802:        btst    IMM (DBL_MANT_DIG+1),d0 
                    803:        beq     1f
                    804:        lsrl    IMM (1),d0
                    805:        roxrl   IMM (1),d1
                    806:        roxrl   IMM (1),d2
                    807:        roxrl   IMM (1),d3
                    808:        addw    IMM (1),d4
                    809: 1:
                    810:        lea     Lsubdf$1,a0     | to return from rounding routine
                    811:        lea     SYM (_fpCCR),a1 | check the rounding mode
                    812:        movew   a1@(6),d6       | rounding mode in d6
                    813:        beq     Lround$to$nearest
                    814:        cmpw    IMM (ROUND_TO_PLUS),d6
                    815:        bhi     Lround$to$minus
                    816:        blt     Lround$to$zero
                    817:        bra     Lround$to$plus
                    818: Lsubdf$1:
                    819: | Put back the exponent and sign (we don't have overflow). '
                    820:        bclr    IMM (DBL_MANT_DIG-1),d0 
                    821:        lslw    IMM (4),d4      | put exponent back into position
                    822:        swap    d0              | 
                    823:        orw     d4,d0           |
                    824:        swap    d0              |
                    825:        bra     Ladddf$ret
                    826: 
                    827: | If one of the numbers was too small (difference of exponents >= 
                    828: | DBL_MANT_DIG+1) we return the other (and now we don't have to '
                    829: | check for finiteness or zero).
                    830: Ladddf$a$small:
                    831:        moveml  sp@+,a2-a3      
                    832:        movel   a6@(16),d0
                    833:        movel   a6@(20),d1
                    834:        lea     SYM (_fpCCR),a0
                    835:        movew   IMM (0),a0@
                    836:        moveml  sp@+,d2-d7      | restore data registers
                    837:        unlk    a6              | and return
                    838:        rts
                    839: 
                    840: Ladddf$b$small:
                    841:        moveml  sp@+,a2-a3      
                    842:        movel   a6@(8),d0
                    843:        movel   a6@(12),d1
                    844:        lea     SYM (_fpCCR),a0
                    845:        movew   IMM (0),a0@
                    846:        moveml  sp@+,d2-d7      | restore data registers
                    847:        unlk    a6              | and return
                    848:        rts
                    849: 
                    850: Ladddf$a$den:
                    851:        movel   d7,d4           | d7 contains 0x00200000
                    852:        bra     Ladddf$1
                    853: 
                    854: Ladddf$b$den:
                    855:        movel   d7,d5           | d7 contains 0x00200000
                    856:        notl    d6
                    857:        bra     Ladddf$2
                    858: 
                    859: Ladddf$b:
                    860: | Return b (if a is zero)
                    861:        movel   d2,d0
                    862:        movel   d3,d1
                    863:        bra     1f
                    864: Ladddf$a:
                    865:        movel   a6@(8),d0
                    866:        movel   a6@(12),d1
                    867: 1:
                    868:        movew   IMM (ADD),d5
                    869: | Check for NaN and +/-INFINITY.
                    870:        movel   d0,d7                   |
                    871:        andl    IMM (0x80000000),d7     |
                    872:        bclr    IMM (31),d0             |
                    873:        cmpl    IMM (0x7ff00000),d0     |
                    874:        bge     2f                      |
                    875:        movel   d0,d0                   | check for zero, since we don't  '
                    876:        bne     Ladddf$ret              | want to return -0 by mistake
                    877:        bclr    IMM (31),d7             |
                    878:        bra     Ladddf$ret              |
                    879: 2:
                    880:        andl    IMM (0x000fffff),d0     | check for NaN (nonzero fraction)
                    881:        orl     d1,d0                   |
                    882:        bne     Ld$inop                 |
                    883:        bra     Ld$infty                |
                    884:        
                    885: Ladddf$ret$1:
                    886:        moveml  sp@+,a2-a3      | restore regs and exit
                    887: 
                    888: Ladddf$ret:
                    889: | Normal exit.
                    890:        lea     SYM (_fpCCR),a0
                    891:        movew   IMM (0),a0@
                    892:        orl     d7,d0           | put sign bit back
                    893:        moveml  sp@+,d2-d7
                    894:        unlk    a6
                    895:        rts
                    896: 
                    897: Ladddf$ret$den:
                    898: | Return a denormalized number.
                    899:        lsrl    IMM (1),d0      | shift right once more
                    900:        roxrl   IMM (1),d1      |
                    901:        bra     Ladddf$ret
                    902: 
                    903: Ladddf$nf:
                    904:        movew   IMM (ADD),d5
                    905: | This could be faster but it is not worth the effort, since it is not
                    906: | executed very often. We sacrifice speed for clarity here.
                    907:        movel   a6@(8),d0       | get the numbers back (remember that we
                    908:        movel   a6@(12),d1      | did some processing already)
                    909:        movel   a6@(16),d2      | 
                    910:        movel   a6@(20),d3      | 
                    911:        movel   IMM (0x7ff00000),d4 | useful constant (INFINITY)
                    912:        movel   d0,d7           | save sign bits
                    913:        movel   d2,d6           | 
                    914:        bclr    IMM (31),d0     | clear sign bits
                    915:        bclr    IMM (31),d2     | 
                    916: | We know that one of them is either NaN of +/-INFINITY
                    917: | Check for NaN (if either one is NaN return NaN)
                    918:        cmpl    d4,d0           | check first a (d0)
                    919:        bhi     Ld$inop         | if d0 > 0x7ff00000 or equal and
                    920:        bne     2f
                    921:        tstl    d1              | d1 > 0, a is NaN
                    922:        bne     Ld$inop         | 
                    923: 2:     cmpl    d4,d2           | check now b (d1)
                    924:        bhi     Ld$inop         | 
                    925:        bne     3f
                    926:        tstl    d3              | 
                    927:        bne     Ld$inop         | 
                    928: 3:
                    929: | Now comes the check for +/-INFINITY. We know that both are (maybe not
                    930: | finite) numbers, but we have to check if both are infinite whether we
                    931: | are adding or subtracting them.
                    932:        eorl    d7,d6           | to check sign bits
                    933:        bmi     1f
                    934:        andl    IMM (0x80000000),d7 | get (common) sign bit
                    935:        bra     Ld$infty
                    936: 1:
                    937: | We know one (or both) are infinite, so we test for equality between the
                    938: | two numbers (if they are equal they have to be infinite both, so we
                    939: | return NaN).
                    940:        cmpl    d2,d0           | are both infinite?
                    941:        bne     1f              | if d0 <> d2 they are not equal
                    942:        cmpl    d3,d1           | if d0 == d2 test d3 and d1
                    943:        beq     Ld$inop         | if equal return NaN
                    944: 1:     
                    945:        andl    IMM (0x80000000),d7 | get a's sign bit '
                    946:        cmpl    d4,d0           | test now for infinity
                    947:        beq     Ld$infty        | if a is INFINITY return with this sign
                    948:        bchg    IMM (31),d7     | else we know b is INFINITY and has
                    949:        bra     Ld$infty        | the opposite sign
                    950: 
                    951: |=============================================================================
                    952: |                              __muldf3
                    953: |=============================================================================
                    954: 
                    955: | double __muldf3(double, double);
                    956: SYM (__muldf3):
                    957:        link    a6,IMM (0)
                    958:        moveml  d2-d7,sp@-
                    959:        movel   a6@(8),d0               | get a into d0-d1
                    960:        movel   a6@(12),d1              | 
                    961:        movel   a6@(16),d2              | and b into d2-d3
                    962:        movel   a6@(20),d3              |
                    963:        movel   d0,d7                   | d7 will hold the sign of the product
                    964:        eorl    d2,d7                   |
                    965:        andl    IMM (0x80000000),d7     |
                    966:        movel   d7,a0                   | save sign bit into a0 
                    967:        movel   IMM (0x7ff00000),d7     | useful constant (+INFINITY)
                    968:        movel   d7,d6                   | another (mask for fraction)
                    969:        notl    d6                      |
                    970:        bclr    IMM (31),d0             | get rid of a's sign bit '
                    971:        movel   d0,d4                   | 
                    972:        orl     d1,d4                   | 
                    973:        beq     Lmuldf$a$0              | branch if a is zero
                    974:        movel   d0,d4                   |
                    975:        bclr    IMM (31),d2             | get rid of b's sign bit '
                    976:        movel   d2,d5                   |
                    977:        orl     d3,d5                   | 
                    978:        beq     Lmuldf$b$0              | branch if b is zero
                    979:        movel   d2,d5                   | 
                    980:        cmpl    d7,d0                   | is a big?
                    981:        bhi     Lmuldf$inop             | if a is NaN return NaN
                    982:        beq     Lmuldf$a$nf             | we still have to check d1 and b ...
                    983:        cmpl    d7,d2                   | now compare b with INFINITY
                    984:        bhi     Lmuldf$inop             | is b NaN?
                    985:        beq     Lmuldf$b$nf             | we still have to check d3 ...
                    986: | Here we have both numbers finite and nonzero (and with no sign bit).
                    987: | Now we get the exponents into d4 and d5.
                    988:        andl    d7,d4                   | isolate exponent in d4
                    989:        beq     Lmuldf$a$den            | if exponent zero, have denormalized
                    990:        andl    d6,d0                   | isolate fraction
                    991:        orl     IMM (0x00100000),d0     | and put hidden bit back
                    992:        swap    d4                      | I like exponents in the first byte
                    993:        lsrw    IMM (4),d4              | 
                    994: Lmuldf$1:                      
                    995:        andl    d7,d5                   |
                    996:        beq     Lmuldf$b$den            |
                    997:        andl    d6,d2                   |
                    998:        orl     IMM (0x00100000),d2     | and put hidden bit back
                    999:        swap    d5                      |
                   1000:        lsrw    IMM (4),d5              |
                   1001: Lmuldf$2:                              |
                   1002:        addw    d5,d4                   | add exponents
                   1003:        subw    IMM (D_BIAS+1),d4       | and subtract bias (plus one)
                   1004: 
                   1005: | We are now ready to do the multiplication. The situation is as follows:
                   1006: | both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were 
                   1007: | denormalized to start with!), which means that in the product bit 104 
                   1008: | (which will correspond to bit 8 of the fourth long) is set.
                   1009: 
                   1010: | Here we have to do the product.
                   1011: | To do it we have to juggle the registers back and forth, as there are not
                   1012: | enough to keep everything in them. So we use the address registers to keep
                   1013: | some intermediate data.
                   1014: 
                   1015:        moveml  a2-a3,sp@-      | save a2 and a3 for temporary use
                   1016:        movel   IMM (0),a2      | a2 is a null register
                   1017:        movel   d4,a3           | and a3 will preserve the exponent
                   1018: 
                   1019: | First, shift d2-d3 so bit 20 becomes bit 31:
                   1020:        rorl    IMM (5),d2      | rotate d2 5 places right
                   1021:        swap    d2              | and swap it
                   1022:        rorl    IMM (5),d3      | do the same thing with d3
                   1023:        swap    d3              |
                   1024:        movew   d3,d6           | get the rightmost 11 bits of d3
                   1025:        andw    IMM (0x07ff),d6 |
                   1026:        orw     d6,d2           | and put them into d2
                   1027:        andw    IMM (0xf800),d3 | clear those bits in d3
                   1028: 
                   1029:        movel   d2,d6           | move b into d6-d7
                   1030:        movel   d3,d7           | move a into d4-d5
                   1031:        movel   d0,d4           | and clear d0-d1-d2-d3 (to put result)
                   1032:        movel   d1,d5           |
                   1033:        movel   IMM (0),d3      |
                   1034:        movel   d3,d2           |
                   1035:        movel   d3,d1           |
                   1036:        movel   d3,d0           |
                   1037: 
                   1038: | We use a1 as counter:        
                   1039:        movel   IMM (DBL_MANT_DIG-1),a1         
                   1040:        exg     d7,a1
                   1041: 
                   1042: 1:     exg     d7,a1           | put counter back in a1
                   1043:        addl    d3,d3           | shift sum once left
                   1044:        addxl   d2,d2           |
                   1045:        addxl   d1,d1           |
                   1046:        addxl   d0,d0           |
                   1047:        addl    d7,d7           |
                   1048:        addxl   d6,d6           |
                   1049:        bcc     2f              | if bit clear skip the following
                   1050:        exg     d7,a2           |
                   1051:        addl    d5,d3           | else add a to the sum
                   1052:        addxl   d4,d2           |
                   1053:        addxl   d7,d1           |
                   1054:        addxl   d7,d0           |
                   1055:        exg     d7,a2           | 
                   1056: 2:     exg     d7,a1           | put counter in d7
                   1057:        dbf     d7,1b           | decrement and branch
                   1058: 
                   1059:        movel   a3,d4           | restore exponent
                   1060:        moveml  sp@+,a2-a3
                   1061: 
                   1062: | Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The 
                   1063: | first thing to do now is to normalize it so bit 8 becomes bit 
                   1064: | DBL_MANT_DIG-32 (to do the rounding); later we will shift right.
                   1065:        swap    d0
                   1066:        swap    d1
                   1067:        movew   d1,d0
                   1068:        swap    d2
                   1069:        movew   d2,d1
                   1070:        swap    d3
                   1071:        movew   d3,d2
                   1072:        movew   IMM (0),d3
                   1073:        lsrl    IMM (1),d0
                   1074:        roxrl   IMM (1),d1
                   1075:        roxrl   IMM (1),d2
                   1076:        roxrl   IMM (1),d3
                   1077:        lsrl    IMM (1),d0
                   1078:        roxrl   IMM (1),d1
                   1079:        roxrl   IMM (1),d2
                   1080:        roxrl   IMM (1),d3
                   1081:        lsrl    IMM (1),d0
                   1082:        roxrl   IMM (1),d1
                   1083:        roxrl   IMM (1),d2
                   1084:        roxrl   IMM (1),d3
                   1085:        
                   1086: | Now round, check for over- and underflow, and exit.
                   1087:        movel   a0,d7           | get sign bit back into d7
                   1088:        movew   IMM (MULTIPLY),d5
                   1089: 
                   1090:        btst    IMM (DBL_MANT_DIG+1-32),d0
                   1091:        beq     Lround$exit
                   1092:        lsrl    IMM (1),d0
                   1093:        roxrl   IMM (1),d1
                   1094:        addw    IMM (1),d4
                   1095:        bra     Lround$exit
                   1096: 
                   1097: Lmuldf$inop:
                   1098:        movew   IMM (MULTIPLY),d5
                   1099:        bra     Ld$inop
                   1100: 
                   1101: Lmuldf$b$nf:
                   1102:        movew   IMM (MULTIPLY),d5
                   1103:        movel   a0,d7           | get sign bit back into d7
                   1104:        tstl    d3              | we know d2 == 0x7ff00000, so check d3
                   1105:        bne     Ld$inop         | if d3 <> 0 b is NaN
                   1106:        bra     Ld$overflow     | else we have overflow (since a is finite)
                   1107: 
                   1108: Lmuldf$a$nf:
                   1109:        movew   IMM (MULTIPLY),d5
                   1110:        movel   a0,d7           | get sign bit back into d7
                   1111:        tstl    d1              | we know d0 == 0x7ff00000, so check d1
                   1112:        bne     Ld$inop         | if d1 <> 0 a is NaN
                   1113:        bra     Ld$overflow     | else signal overflow
                   1114: 
                   1115: | If either number is zero return zero, unless the other is +/-INFINITY or
                   1116: | NaN, in which case we return NaN.
                   1117: Lmuldf$b$0:
                   1118:        movew   IMM (MULTIPLY),d5
                   1119:        exg     d2,d0           | put b (==0) into d0-d1
                   1120:        exg     d3,d1           | and a (with sign bit cleared) into d2-d3
                   1121:        bra     1f
                   1122: Lmuldf$a$0:
                   1123:        movel   a6@(16),d2      | put b into d2-d3 again
                   1124:        movel   a6@(20),d3      |
                   1125:        bclr    IMM (31),d2     | clear sign bit
                   1126: 1:     cmpl    IMM (0x7ff00000),d2 | check for non-finiteness
                   1127:        bge     Ld$inop         | in case NaN or +/-INFINITY return NaN
                   1128:        lea     SYM (_fpCCR),a0
                   1129:        movew   IMM (0),a0@
                   1130:        moveml  sp@+,d2-d7
                   1131:        unlk    a6
                   1132:        rts
                   1133: 
                   1134: | If a number is denormalized we put an exponent of 1 but do not put the 
                   1135: | hidden bit back into the fraction; instead we shift left until bit 21
                   1136: | (the hidden bit) is set, adjusting the exponent accordingly. We do this
                   1137: | to ensure that the product of the fractions is close to 1.
                   1138: Lmuldf$a$den:
                   1139:        movel   IMM (1),d4
                   1140:        andl    d6,d0
                   1141: 1:     addl    d1,d1           | shift a left until bit 20 is set
                   1142:        addxl   d0,d0           |
                   1143:        subw    IMM (1),d4      | and adjust exponent
                   1144:        btst    IMM (20),d0     |
                   1145:        bne     Lmuldf$1        |
                   1146:        bra     1b
                   1147: 
                   1148: Lmuldf$b$den:
                   1149:        movel   IMM (1),d5
                   1150:        andl    d6,d2
                   1151: 1:     addl    d3,d3           | shift b left until bit 20 is set
                   1152:        addxl   d2,d2           |
                   1153:        subw    IMM (1),d5      | and adjust exponent
                   1154:        btst    IMM (20),d2     |
                   1155:        bne     Lmuldf$2        |
                   1156:        bra     1b
                   1157: 
                   1158: 
                   1159: |=============================================================================
                   1160: |                              __divdf3
                   1161: |=============================================================================
                   1162: 
                   1163: | double __divdf3(double, double);
                   1164: SYM (__divdf3):
                   1165:        link    a6,IMM (0)
                   1166:        moveml  d2-d7,sp@-
                   1167:        movel   a6@(8),d0       | get a into d0-d1
                   1168:        movel   a6@(12),d1      | 
                   1169:        movel   a6@(16),d2      | and b into d2-d3
                   1170:        movel   a6@(20),d3      |
                   1171:        movel   d0,d7           | d7 will hold the sign of the result
                   1172:        eorl    d2,d7           |
                   1173:        andl    IMM (0x80000000),d7
                   1174:        movel   d7,a0           | save sign into a0
                   1175:        movel   IMM (0x7ff00000),d7 | useful constant (+INFINITY)
                   1176:        movel   d7,d6           | another (mask for fraction)
                   1177:        notl    d6              |
                   1178:        bclr    IMM (31),d0     | get rid of a's sign bit '
                   1179:        movel   d0,d4           |
                   1180:        orl     d1,d4           |
                   1181:        beq     Ldivdf$a$0      | branch if a is zero
                   1182:        movel   d0,d4           |
                   1183:        bclr    IMM (31),d2     | get rid of b's sign bit '
                   1184:        movel   d2,d5           |
                   1185:        orl     d3,d5           |
                   1186:        beq     Ldivdf$b$0      | branch if b is zero
                   1187:        movel   d2,d5
                   1188:        cmpl    d7,d0           | is a big?
                   1189:        bhi     Ldivdf$inop     | if a is NaN return NaN
                   1190:        beq     Ldivdf$a$nf     | if d0 == 0x7ff00000 we check d1
                   1191:        cmpl    d7,d2           | now compare b with INFINITY 
                   1192:        bhi     Ldivdf$inop     | if b is NaN return NaN
                   1193:        beq     Ldivdf$b$nf     | if d2 == 0x7ff00000 we check d3
                   1194: | Here we have both numbers finite and nonzero (and with no sign bit).
                   1195: | Now we get the exponents into d4 and d5 and normalize the numbers to
                   1196: | ensure that the ratio of the fractions is around 1. We do this by
                   1197: | making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit)
                   1198: | set, even if they were denormalized to start with.
                   1199: | Thus, the result will satisfy: 2 > result > 1/2.
                   1200:        andl    d7,d4           | and isolate exponent in d4
                   1201:        beq     Ldivdf$a$den    | if exponent is zero we have a denormalized
                   1202:        andl    d6,d0           | and isolate fraction
                   1203:        orl     IMM (0x00100000),d0 | and put hidden bit back
                   1204:        swap    d4              | I like exponents in the first byte
                   1205:        lsrw    IMM (4),d4      | 
                   1206: Ldivdf$1:                      | 
                   1207:        andl    d7,d5           |
                   1208:        beq     Ldivdf$b$den    |
                   1209:        andl    d6,d2           |
                   1210:        orl     IMM (0x00100000),d2
                   1211:        swap    d5              |
                   1212:        lsrw    IMM (4),d5      |
                   1213: Ldivdf$2:                      |
                   1214:        subw    d5,d4           | subtract exponents
                   1215:        addw    IMM (D_BIAS),d4 | and add bias
                   1216: 
                   1217: | We are now ready to do the division. We have prepared things in such a way
                   1218: | that the ratio of the fractions will be less than 2 but greater than 1/2.
                   1219: | At this point the registers in use are:
                   1220: | d0-d1        hold a (first operand, bit DBL_MANT_DIG-32=0, bit 
                   1221: | DBL_MANT_DIG-1-32=1)
                   1222: | d2-d3        hold b (second operand, bit DBL_MANT_DIG-32=1)
                   1223: | d4   holds the difference of the exponents, corrected by the bias
                   1224: | a0   holds the sign of the ratio
                   1225: 
                   1226: | To do the rounding correctly we need to keep information about the
                   1227: | nonsignificant bits. One way to do this would be to do the division
                   1228: | using four registers; another is to use two registers (as originally
                   1229: | I did), but use a sticky bit to preserve information about the 
                   1230: | fractional part. Note that we can keep that info in a1, which is not
                   1231: | used.
                   1232:        movel   IMM (0),d6      | d6-d7 will hold the result
                   1233:        movel   d6,d7           | 
                   1234:        movel   IMM (0),a1      | and a1 will hold the sticky bit
                   1235: 
                   1236:        movel   IMM (DBL_MANT_DIG-32+1),d5      
                   1237:        
                   1238: 1:     cmpl    d0,d2           | is a < b?
                   1239:        bhi     3f              | if b > a skip the following
                   1240:        beq     4f              | if d0==d2 check d1 and d3
                   1241: 2:     subl    d3,d1           | 
                   1242:        subxl   d2,d0           | a <-- a - b
                   1243:        bset    d5,d6           | set the corresponding bit in d6
                   1244: 3:     addl    d1,d1           | shift a by 1
                   1245:        addxl   d0,d0           |
                   1246:        dbra    d5,1b           | and branch back
                   1247:        bra     5f                      
                   1248: 4:     cmpl    d1,d3           | here d0==d2, so check d1 and d3
                   1249:        bhi     3b              | if d1 > d2 skip the subtraction
                   1250:        bra     2b              | else go do it
                   1251: 5:
                   1252: | Here we have to start setting the bits in the second long.
                   1253:        movel   IMM (31),d5     | again d5 is counter
                   1254: 
                   1255: 1:     cmpl    d0,d2           | is a < b?
                   1256:        bhi     3f              | if b > a skip the following
                   1257:        beq     4f              | if d0==d2 check d1 and d3
                   1258: 2:     subl    d3,d1           | 
                   1259:        subxl   d2,d0           | a <-- a - b
                   1260:        bset    d5,d7           | set the corresponding bit in d7
                   1261: 3:     addl    d1,d1           | shift a by 1
                   1262:        addxl   d0,d0           |
                   1263:        dbra    d5,1b           | and branch back
                   1264:        bra     5f                      
                   1265: 4:     cmpl    d1,d3           | here d0==d2, so check d1 and d3
                   1266:        bhi     3b              | if d1 > d2 skip the subtraction
                   1267:        bra     2b              | else go do it
                   1268: 5:
                   1269: | Now go ahead checking until we hit a one, which we store in d2.
                   1270:        movel   IMM (DBL_MANT_DIG),d5
                   1271: 1:     cmpl    d2,d0           | is a < b?
                   1272:        bhi     4f              | if b < a, exit
                   1273:        beq     3f              | if d0==d2 check d1 and d3
                   1274: 2:     addl    d1,d1           | shift a by 1
                   1275:        addxl   d0,d0           |
                   1276:        dbra    d5,1b           | and branch back
                   1277:        movel   IMM (0),d2      | here no sticky bit was found
                   1278:        movel   d2,d3
                   1279:        bra     5f                      
                   1280: 3:     cmpl    d1,d3           | here d0==d2, so check d1 and d3
                   1281:        bhi     2b              | if d1 > d2 go back
                   1282: 4:
                   1283: | Here put the sticky bit in d2-d3 (in the position which actually corresponds
                   1284: | to it; if you don't do this the algorithm loses in some cases). '
                   1285:        movel   IMM (0),d2
                   1286:        movel   d2,d3
                   1287:        subw    IMM (DBL_MANT_DIG),d5
                   1288:        addw    IMM (63),d5
                   1289:        cmpw    IMM (31),d5
                   1290:        bhi     2f
                   1291: 1:     bset    d5,d3
                   1292:        bra     5f
                   1293:        subw    IMM (32),d5
                   1294: 2:     bset    d5,d2
                   1295: 5:
                   1296: | Finally we are finished! Move the longs in the address registers to
                   1297: | their final destination:
                   1298:        movel   d6,d0
                   1299:        movel   d7,d1
                   1300:        movel   IMM (0),d3
                   1301: 
                   1302: | Here we have finished the division, with the result in d0-d1-d2-d3, with
                   1303: | 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set.
                   1304: | If it is not, then definitely bit 21 is set. Normalize so bit 22 is
                   1305: | not set:
                   1306:        btst    IMM (DBL_MANT_DIG-32+1),d0
                   1307:        beq     1f
                   1308:        lsrl    IMM (1),d0
                   1309:        roxrl   IMM (1),d1
                   1310:        roxrl   IMM (1),d2
                   1311:        roxrl   IMM (1),d3
                   1312:        addw    IMM (1),d4
                   1313: 1:
                   1314: | Now round, check for over- and underflow, and exit.
                   1315:        movel   a0,d7           | restore sign bit to d7
                   1316:        movew   IMM (DIVIDE),d5
                   1317:        bra     Lround$exit
                   1318: 
                   1319: Ldivdf$inop:
                   1320:        movew   IMM (DIVIDE),d5
                   1321:        bra     Ld$inop
                   1322: 
                   1323: Ldivdf$a$0:
                   1324: | If a is zero check to see whether b is zero also. In that case return
                   1325: | NaN; then check if b is NaN, and return NaN also in that case. Else
                   1326: | return zero.
                   1327:        movew   IMM (DIVIDE),d5
                   1328:        bclr    IMM (31),d2     |
                   1329:        movel   d2,d4           | 
                   1330:        orl     d3,d4           | 
                   1331:        beq     Ld$inop         | if b is also zero return NaN
                   1332:        cmpl    IMM (0x7ff00000),d2 | check for NaN
                   1333:        bhi     Ld$inop         | 
                   1334:        blt     1f              |
                   1335:        tstl    d3              |
                   1336:        bne     Ld$inop         |
                   1337: 1:     movel   IMM (0),d0      | else return zero
                   1338:        movel   d0,d1           | 
                   1339:        lea     SYM (_fpCCR),a0 | clear exception flags
                   1340:        movew   IMM (0),a0@     |
                   1341:        moveml  sp@+,d2-d7      | 
                   1342:        unlk    a6              | 
                   1343:        rts                     |       
                   1344: 
                   1345: Ldivdf$b$0:
                   1346:        movew   IMM (DIVIDE),d5
                   1347: | If we got here a is not zero. Check if a is NaN; in that case return NaN,
                   1348: | else return +/-INFINITY. Remember that a is in d0 with the sign bit 
                   1349: | cleared already.
                   1350:        movel   a0,d7           | put a's sign bit back in d7 '
                   1351:        cmpl    IMM (0x7ff00000),d0 | compare d0 with INFINITY
                   1352:        bhi     Ld$inop         | if larger it is NaN
                   1353:        tstl    d1              | 
                   1354:        bne     Ld$inop         | 
                   1355:        bra     Ld$div$0        | else signal DIVIDE_BY_ZERO
                   1356: 
                   1357: Ldivdf$b$nf:
                   1358:        movew   IMM (DIVIDE),d5
                   1359: | If d2 == 0x7ff00000 we have to check d3.
                   1360:        tstl    d3              |
                   1361:        bne     Ld$inop         | if d3 <> 0, b is NaN
                   1362:        bra     Ld$underflow    | else b is +/-INFINITY, so signal underflow
                   1363: 
                   1364: Ldivdf$a$nf:
                   1365:        movew   IMM (DIVIDE),d5
                   1366: | If d0 == 0x7ff00000 we have to check d1.
                   1367:        tstl    d1              |
                   1368:        bne     Ld$inop         | if d1 <> 0, a is NaN
                   1369: | If a is INFINITY we have to check b
                   1370:        cmpl    d7,d2           | compare b with INFINITY 
                   1371:        bge     Ld$inop         | if b is NaN or INFINITY return NaN
                   1372:        tstl    d3              |
                   1373:        bne     Ld$inop         | 
                   1374:        bra     Ld$overflow     | else return overflow
                   1375: 
                   1376: | If a number is denormalized we put an exponent of 1 but do not put the 
                   1377: | bit back into the fraction.
                   1378: Ldivdf$a$den:
                   1379:        movel   IMM (1),d4
                   1380:        andl    d6,d0
                   1381: 1:     addl    d1,d1           | shift a left until bit 20 is set
                   1382:        addxl   d0,d0
                   1383:        subw    IMM (1),d4      | and adjust exponent
                   1384:        btst    IMM (DBL_MANT_DIG-32-1),d0
                   1385:        bne     Ldivdf$1
                   1386:        bra     1b
                   1387: 
                   1388: Ldivdf$b$den:
                   1389:        movel   IMM (1),d5
                   1390:        andl    d6,d2
                   1391: 1:     addl    d3,d3           | shift b left until bit 20 is set
                   1392:        addxl   d2,d2
                   1393:        subw    IMM (1),d5      | and adjust exponent
                   1394:        btst    IMM (DBL_MANT_DIG-32-1),d2
                   1395:        bne     Ldivdf$2
                   1396:        bra     1b
                   1397: 
                   1398: Lround$exit:
                   1399: | This is a common exit point for __muldf3 and __divdf3. When they enter
                   1400: | this point the sign of the result is in d7, the result in d0-d1, normalized
                   1401: | so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4.
                   1402: 
                   1403: | First check for underlow in the exponent:
                   1404:        cmpw    IMM (-DBL_MANT_DIG-1),d4                
                   1405:        blt     Ld$underflow    
                   1406: | It could happen that the exponent is less than 1, in which case the 
                   1407: | number is denormalized. In this case we shift right and adjust the 
                   1408: | exponent until it becomes 1 or the fraction is zero (in the latter case 
                   1409: | we signal underflow and return zero).
                   1410:        movel   d7,a0           |
                   1411:        movel   IMM (0),d6      | use d6-d7 to collect bits flushed right
                   1412:        movel   d6,d7           | use d6-d7 to collect bits flushed right
                   1413:        cmpw    IMM (1),d4      | if the exponent is less than 1 we 
                   1414:        bge     2f              | have to shift right (denormalize)
                   1415: 1:     addw    IMM (1),d4      | adjust the exponent
                   1416:        lsrl    IMM (1),d0      | shift right once 
                   1417:        roxrl   IMM (1),d1      |
                   1418:        roxrl   IMM (1),d2      |
                   1419:        roxrl   IMM (1),d3      |
                   1420:        roxrl   IMM (1),d6      | 
                   1421:        roxrl   IMM (1),d7      |
                   1422:        cmpw    IMM (1),d4      | is the exponent 1 already?
                   1423:        beq     2f              | if not loop back
                   1424:        bra     1b              |
                   1425:        bra     Ld$underflow    | safety check, shouldn't execute '
                   1426: 2:     orl     d6,d2           | this is a trick so we don't lose  '
                   1427:        orl     d7,d3           | the bits which were flushed right
                   1428:        movel   a0,d7           | get back sign bit into d7
                   1429: | Now call the rounding routine (which takes care of denormalized numbers):
                   1430:        lea     Lround$0,a0     | to return from rounding routine
                   1431:        lea     SYM (_fpCCR),a1 | check the rounding mode
                   1432:        movew   a1@(6),d6       | rounding mode in d6
                   1433:        beq     Lround$to$nearest
                   1434:        cmpw    IMM (ROUND_TO_PLUS),d6
                   1435:        bhi     Lround$to$minus
                   1436:        blt     Lround$to$zero
                   1437:        bra     Lround$to$plus
                   1438: Lround$0:
                   1439: | Here we have a correctly rounded result (either normalized or denormalized).
                   1440: 
                   1441: | Here we should have either a normalized number or a denormalized one, and
                   1442: | the exponent is necessarily larger or equal to 1 (so we don't have to  '
                   1443: | check again for underflow!). We have to check for overflow or for a 
                   1444: | denormalized number (which also signals underflow).
                   1445: | Check for overflow (i.e., exponent >= 0x7ff).
                   1446:        cmpw    IMM (0x07ff),d4
                   1447:        bge     Ld$overflow
                   1448: | Now check for a denormalized number (exponent==0):
                   1449:        movew   d4,d4
                   1450:        beq     Ld$den
                   1451: 1:
                   1452: | Put back the exponents and sign and return.
                   1453:        lslw    IMM (4),d4      | exponent back to fourth byte
                   1454:        bclr    IMM (DBL_MANT_DIG-32-1),d0
                   1455:        swap    d0              | and put back exponent
                   1456:        orw     d4,d0           | 
                   1457:        swap    d0              |
                   1458:        orl     d7,d0           | and sign also
                   1459: 
                   1460:        lea     SYM (_fpCCR),a0
                   1461:        movew   IMM (0),a0@
                   1462:        moveml  sp@+,d2-d7
                   1463:        unlk    a6
                   1464:        rts
                   1465: 
                   1466: |=============================================================================
                   1467: |                              __negdf2
                   1468: |=============================================================================
                   1469: 
                   1470: | double __negdf2(double, double);
                   1471: SYM (__negdf2):
                   1472:        link    a6,IMM (0)
                   1473:        moveml  d2-d7,sp@-
                   1474:        movew   IMM (NEGATE),d5
                   1475:        movel   a6@(8),d0       | get number to negate in d0-d1
                   1476:        movel   a6@(12),d1      |
                   1477:        bchg    IMM (31),d0     | negate
                   1478:        movel   d0,d2           | make a positive copy (for the tests)
                   1479:        bclr    IMM (31),d2     |
                   1480:        movel   d2,d4           | check for zero
                   1481:        orl     d1,d4           |
                   1482:        beq     2f              | if zero (either sign) return +zero
                   1483:        cmpl    IMM (0x7ff00000),d2 | compare to +INFINITY
                   1484:        blt     1f              | if finite, return
                   1485:        bhi     Ld$inop         | if larger (fraction not zero) is NaN
                   1486:        tstl    d1              | if d2 == 0x7ff00000 check d1
                   1487:        bne     Ld$inop         |
                   1488:        movel   d0,d7           | else get sign and return INFINITY
                   1489:        andl    IMM (0x80000000),d7
                   1490:        bra     Ld$infty                
                   1491: 1:     lea     SYM (_fpCCR),a0
                   1492:        movew   IMM (0),a0@
                   1493:        moveml  sp@+,d2-d7
                   1494:        unlk    a6
                   1495:        rts
                   1496: 2:     bclr    IMM (31),d0
                   1497:        bra     1b
                   1498: 
                   1499: |=============================================================================
                   1500: |                              __cmpdf2
                   1501: |=============================================================================
                   1502: 
                   1503: GREATER =  1
                   1504: LESS    = -1
                   1505: EQUAL   =  0
                   1506: 
                   1507: | int __cmpdf2(double, double);
                   1508: SYM (__cmpdf2):
                   1509:        link    a6,IMM (0)
                   1510:        moveml  d2-d7,sp@-      | save registers
                   1511:        movew   IMM (COMPARE),d5
                   1512:        movel   a6@(8),d0       | get first operand
                   1513:        movel   a6@(12),d1      |
                   1514:        movel   a6@(16),d2      | get second operand
                   1515:        movel   a6@(20),d3      |
                   1516: | First check if a and/or b are (+/-) zero and in that case clear
                   1517: | the sign bit.
                   1518:        movel   d0,d6           | copy signs into d6 (a) and d7(b)
                   1519:        bclr    IMM (31),d0     | and clear signs in d0 and d2
                   1520:        movel   d2,d7           |
                   1521:        bclr    IMM (31),d2     |
                   1522:        cmpl    IMM (0x7fff0000),d0 | check for a == NaN
                   1523:        bhi     Ld$inop         | if d0 > 0x7ff00000, a is NaN
                   1524:        beq     Lcmpdf$a$nf     | if equal can be INFINITY, so check d1
                   1525:        movel   d0,d4           | copy into d4 to test for zero
                   1526:        orl     d1,d4           |
                   1527:        beq     Lcmpdf$a$0      |
                   1528: Lcmpdf$0:
                   1529:        cmpl    IMM (0x7fff0000),d2 | check for b == NaN
                   1530:        bhi     Ld$inop         | if d2 > 0x7ff00000, b is NaN
                   1531:        beq     Lcmpdf$b$nf     | if equal can be INFINITY, so check d3
                   1532:        movel   d2,d4           |
                   1533:        orl     d3,d4           |
                   1534:        beq     Lcmpdf$b$0      |
                   1535: Lcmpdf$1:
                   1536: | Check the signs
                   1537:        eorl    d6,d7
                   1538:        bpl     1f
                   1539: | If the signs are not equal check if a >= 0
                   1540:        tstl    d6
                   1541:        bpl     Lcmpdf$a$gt$b   | if (a >= 0 && b < 0) => a > b
                   1542:        bmi     Lcmpdf$b$gt$a   | if (a < 0 && b >= 0) => a < b
                   1543: 1:
                   1544: | If the signs are equal check for < 0
                   1545:        tstl    d6
                   1546:        bpl     1f
                   1547: | If both are negative exchange them
                   1548:        exg     d0,d2
                   1549:        exg     d1,d3
                   1550: 1:
                   1551: | Now that they are positive we just compare them as longs (does this also
                   1552: | work for denormalized numbers?).
                   1553:        cmpl    d0,d2
                   1554:        bhi     Lcmpdf$b$gt$a   | |b| > |a|
                   1555:        bne     Lcmpdf$a$gt$b   | |b| < |a|
                   1556: | If we got here d0 == d2, so we compare d1 and d3.
                   1557:        cmpl    d1,d3
                   1558:        bhi     Lcmpdf$b$gt$a   | |b| > |a|
                   1559:        bne     Lcmpdf$a$gt$b   | |b| < |a|
                   1560: | If we got here a == b.
                   1561:        movel   IMM (EQUAL),d0
                   1562:        moveml  sp@+,d2-d7      | put back the registers
                   1563:        unlk    a6
                   1564:        rts
                   1565: Lcmpdf$a$gt$b:
                   1566:        movel   IMM (GREATER),d0
                   1567:        moveml  sp@+,d2-d7      | put back the registers
                   1568:        unlk    a6
                   1569:        rts
                   1570: Lcmpdf$b$gt$a:
                   1571:        movel   IMM (LESS),d0
                   1572:        moveml  sp@+,d2-d7      | put back the registers
                   1573:        unlk    a6
                   1574:        rts
                   1575: 
                   1576: Lcmpdf$a$0:    
                   1577:        bclr    IMM (31),d6
                   1578:        bra     Lcmpdf$0
                   1579: Lcmpdf$b$0:
                   1580:        bclr    IMM (31),d7
                   1581:        bra     Lcmpdf$1
                   1582: 
                   1583: Lcmpdf$a$nf:
                   1584:        tstl    d1
                   1585:        bne     Ld$inop
                   1586:        bra     Lcmpdf$0
                   1587: 
                   1588: Lcmpdf$b$nf:
                   1589:        tstl    d3
                   1590:        bne     Ld$inop
                   1591:        bra     Lcmpdf$1
                   1592: 
                   1593: |=============================================================================
                   1594: |                           rounding routines
                   1595: |=============================================================================
                   1596: 
                   1597: | The rounding routines expect the number to be normalized in registers
                   1598: | d0-d1-d2-d3, with the exponent in register d4. They assume that the 
                   1599: | exponent is larger or equal to 1. They return a properly normalized number
                   1600: | if possible, and a denormalized number otherwise. The exponent is returned
                   1601: | in d4.
                   1602: 
                   1603: Lround$to$nearest:
                   1604: | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
                   1605: | Here we assume that the exponent is not too small (this should be checked
                   1606: | before entering the rounding routine), but the number could be denormalized.
                   1607: 
                   1608: | Check for denormalized numbers:
                   1609: 1:     btst    IMM (DBL_MANT_DIG-32),d0
                   1610:        bne     2f              | if set the number is normalized
                   1611: | Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent 
                   1612: | is one (remember that a denormalized number corresponds to an 
                   1613: | exponent of -D_BIAS+1).
                   1614:        cmpw    IMM (1),d4      | remember that the exponent is at least one
                   1615:        beq     2f              | an exponent of one means denormalized
                   1616:        addl    d3,d3           | else shift and adjust the exponent
                   1617:        addxl   d2,d2           |
                   1618:        addxl   d1,d1           |
                   1619:        addxl   d0,d0           |
                   1620:        dbra    d4,1b           |
                   1621: 2:
                   1622: | Now round: we do it as follows: after the shifting we can write the
                   1623: | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
                   1624: | If delta < 1, do nothing. If delta > 1, add 1 to f. 
                   1625: | If delta == 1, we make sure the rounded number will be even (odd?) 
                   1626: | (after shifting).
                   1627:        btst    IMM (0),d1      | is delta < 1?
                   1628:        beq     2f              | if so, do not do anything
                   1629:        orl     d2,d3           | is delta == 1?
                   1630:        bne     1f              | if so round to even
                   1631:        movel   d1,d3           | 
                   1632:        andl    IMM (2),d3      | bit 1 is the last significant bit
                   1633:        movel   IMM (0),d2      |
                   1634:        addl    d3,d1           |
                   1635:        addxl   d2,d0           |
                   1636:        bra     2f              | 
                   1637: 1:     movel   IMM (1),d3      | else add 1 
                   1638:        movel   IMM (0),d2      |
                   1639:        addl    d3,d1           |
                   1640:        addxl   d2,d0
                   1641: | Shift right once (because we used bit #DBL_MANT_DIG-32!).
                   1642: 2:     lsrl    IMM (1),d0
                   1643:        roxrl   IMM (1),d1              
                   1644: 
                   1645: | Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a
                   1646: | 'fraction overflow' ...).
                   1647:        btst    IMM (DBL_MANT_DIG-32),d0        
                   1648:        beq     1f
                   1649:        lsrl    IMM (1),d0
                   1650:        roxrl   IMM (1),d1
                   1651:        addw    IMM (1),d4
                   1652: 1:
                   1653: | If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we 
                   1654: | have to put the exponent to zero and return a denormalized number.
                   1655:        btst    IMM (DBL_MANT_DIG-32-1),d0
                   1656:        beq     1f
                   1657:        jmp     a0@
                   1658: 1:     movel   IMM (0),d4
                   1659:        jmp     a0@
                   1660: 
                   1661: Lround$to$zero:
                   1662: Lround$to$plus:
                   1663: Lround$to$minus:
                   1664:        jmp     a0@
                   1665: #endif /* L_double */
                   1666: 
                   1667: #ifdef  L_float
                   1668: 
                   1669:        .globl  SYM (_fpCCR)
                   1670:        .globl  $_exception_handler
                   1671: 
                   1672: QUIET_NaN    = 0xffffffff
                   1673: SIGNL_NaN    = 0x7f800001
                   1674: INFINITY     = 0x7f800000
                   1675: 
                   1676: F_MAX_EXP      = 0xff
                   1677: F_BIAS         = 126
                   1678: FLT_MAX_EXP    = F_MAX_EXP - F_BIAS
                   1679: FLT_MIN_EXP    = 1 - F_BIAS
                   1680: FLT_MANT_DIG   = 24
                   1681: 
                   1682: INEXACT_RESULT                 = 0x0001
                   1683: UNDERFLOW              = 0x0002
                   1684: OVERFLOW               = 0x0004
                   1685: DIVIDE_BY_ZERO                 = 0x0008
                   1686: INVALID_OPERATION      = 0x0010
                   1687: 
                   1688: SINGLE_FLOAT = 1
                   1689: 
                   1690: NOOP         = 0
                   1691: ADD          = 1
                   1692: MULTIPLY     = 2
                   1693: DIVIDE       = 3
                   1694: NEGATE       = 4
                   1695: COMPARE      = 5
                   1696: EXTENDSFDF   = 6
                   1697: TRUNCDFSF    = 7
                   1698: 
                   1699: UNKNOWN           = -1
                   1700: ROUND_TO_NEAREST  = 0 | round result to nearest representable value
                   1701: ROUND_TO_ZERO     = 1 | round result towards zero
                   1702: ROUND_TO_PLUS     = 2 | round result towards plus infinity
                   1703: ROUND_TO_MINUS    = 3 | round result towards minus infinity
                   1704: 
                   1705: | Entry points:
                   1706: 
                   1707:        .globl SYM (__addsf3)
                   1708:        .globl SYM (__subsf3)
                   1709:        .globl SYM (__mulsf3)
                   1710:        .globl SYM (__divsf3)
                   1711:        .globl SYM (__negsf2)
                   1712:        .globl SYM (__cmpsf2)
                   1713: 
                   1714: | These are common routines to return and signal exceptions.   
                   1715: 
                   1716:        .text
                   1717:        .even
                   1718: 
                   1719: Lf$den:
                   1720: | Return and signal a denormalized number
                   1721:        orl     d7,d0
                   1722:        movew   IMM (UNDERFLOW),d7
                   1723:        orw     IMM (INEXACT_RESULT),d7
                   1724:        movew   IMM (SINGLE_FLOAT),d6
                   1725:        jmp     $_exception_handler
                   1726: 
                   1727: Lf$infty:
                   1728: Lf$overflow:
                   1729: | Return a properly signed INFINITY and set the exception flags 
                   1730:        movel   IMM (INFINITY),d0
                   1731:        orl     d7,d0
                   1732:        movew   IMM (OVERFLOW),d7
                   1733:        orw     IMM (INEXACT_RESULT),d7
                   1734:        movew   IMM (SINGLE_FLOAT),d6
                   1735:        jmp     $_exception_handler
                   1736: 
                   1737: Lf$underflow:
                   1738: | Return 0 and set the exception flags 
                   1739:        movel   IMM (0),d0
                   1740:        movew   IMM (UNDERFLOW),d7
                   1741:        orw     IMM (INEXACT_RESULT),d7
                   1742:        movew   IMM (SINGLE_FLOAT),d6
                   1743:        jmp     $_exception_handler
                   1744: 
                   1745: Lf$inop:
                   1746: | Return a quiet NaN and set the exception flags
                   1747:        movel   IMM (QUIET_NaN),d0
                   1748:        movew   IMM (INVALID_OPERATION),d7
                   1749:        orw     IMM (INEXACT_RESULT),d7
                   1750:        movew   IMM (SINGLE_FLOAT),d6
                   1751:        jmp     $_exception_handler
                   1752: 
                   1753: Lf$div$0:
                   1754: | Return a properly signed INFINITY and set the exception flags
                   1755:        movel   IMM (INFINITY),d0
                   1756:        orl     d7,d0
                   1757:        movew   IMM (DIVIDE_BY_ZERO),d7
                   1758:        orw     IMM (INEXACT_RESULT),d7
                   1759:        movew   IMM (SINGLE_FLOAT),d6
                   1760:        jmp     $_exception_handler
                   1761: 
                   1762: |=============================================================================
                   1763: |=============================================================================
                   1764: |                         single precision routines
                   1765: |=============================================================================
                   1766: |=============================================================================
                   1767: 
                   1768: | A single precision floating point number (float) has the format:
                   1769: |
                   1770: | struct _float {
                   1771: |  unsigned int sign      : 1;  /* sign bit */ 
                   1772: |  unsigned int exponent  : 8;  /* exponent, shifted by 126 */
                   1773: |  unsigned int fraction  : 23; /* fraction */
                   1774: | } float;
                   1775: | 
                   1776: | Thus sizeof(float) = 4 (32 bits). 
                   1777: |
                   1778: | All the routines are callable from C programs, and return the result 
                   1779: | in the single register d0. They also preserve all registers except 
                   1780: | d0-d1 and a0-a1.
                   1781: 
                   1782: |=============================================================================
                   1783: |                              __subsf3
                   1784: |=============================================================================
                   1785: 
                   1786: | float __subsf3(float, float);
                   1787: SYM (__subsf3):
                   1788:        bchg    IMM (31),sp@(8) | change sign of second operand
                   1789:                                | and fall through
                   1790: |=============================================================================
                   1791: |                              __addsf3
                   1792: |=============================================================================
                   1793: 
                   1794: | float __addsf3(float, float);
                   1795: SYM (__addsf3):
                   1796:        link    a6,IMM (0)      | everything will be done in registers
                   1797:        moveml  d2-d7,sp@-      | save all data registers but d0-d1
                   1798:        movel   a6@(8),d0       | get first operand
                   1799:        movel   a6@(12),d1      | get second operand
                   1800:        movel   d0,d6           | get d0's sign bit '
                   1801:        addl    d0,d0           | check and clear sign bit of a
                   1802:        beq     Laddsf$b        | if zero return second operand
                   1803:        movel   d1,d7           | save b's sign bit '
                   1804:        addl    d1,d1           | get rid of sign bit
                   1805:        beq     Laddsf$a        | if zero return first operand
                   1806: 
                   1807:        movel   d6,a0           | save signs in address registers
                   1808:        movel   d7,a1           | so we can use d6 and d7
                   1809: 
                   1810: | Get the exponents and check for denormalized and/or infinity.
                   1811: 
                   1812:        movel   IMM (0x00ffffff),d4     | mask to get fraction
                   1813:        movel   IMM (0x01000000),d5     | mask to put hidden bit back
                   1814: 
                   1815:        movel   d0,d6           | save a to get exponent
                   1816:        andl    d4,d0           | get fraction in d0
                   1817:        notl    d4              | make d4 into a mask for the exponent
                   1818:        andl    d4,d6           | get exponent in d6
                   1819:        beq     Laddsf$a$den    | branch if a is denormalized
                   1820:        cmpl    d4,d6           | check for INFINITY or NaN
                   1821:        beq     Laddsf$nf
                   1822:        swap    d6              | put exponent into first word
                   1823:        orl     d5,d0           | and put hidden bit back
                   1824: Laddsf$1:
                   1825: | Now we have a's exponent in d6 (second byte) and the mantissa in d0. '
                   1826:        movel   d1,d7           | get exponent in d7
                   1827:        andl    d4,d7           | 
                   1828:        beq     Laddsf$b$den    | branch if b is denormalized
                   1829:        cmpl    d4,d7           | check for INFINITY or NaN
                   1830:        beq     Laddsf$nf
                   1831:        swap    d7              | put exponent into first word
                   1832:        notl    d4              | make d4 into a mask for the fraction
                   1833:        andl    d4,d1           | get fraction in d1
                   1834:        orl     d5,d1           | and put hidden bit back
                   1835: Laddsf$2:
                   1836: | Now we have b's exponent in d7 (second byte) and the mantissa in d1. '
                   1837: 
                   1838: | Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we 
                   1839: | shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra
                   1840: | bit).
                   1841: 
                   1842:        movel   d1,d2           | move b to d2, since we want to use
                   1843:                                | two registers to do the sum
                   1844:        movel   IMM (0),d1      | and clear the new ones
                   1845:        movel   d1,d3           |
                   1846: 
                   1847: | Here we shift the numbers in registers d0 and d1 so the exponents are the
                   1848: | same, and put the largest exponent in d6. Note that we are using two
                   1849: | registers for each number (see the discussion by D. Knuth in "Seminumerical 
                   1850: | Algorithms").
                   1851:        cmpw    d6,d7           | compare exponents
                   1852:        beq     Laddsf$3        | if equal don't shift '
                   1853:        bhi     5f              | branch if second exponent largest
                   1854: 1:
                   1855:        subl    d6,d7           | keep the largest exponent
                   1856:        negl    d7
                   1857:        lsrw    IMM (8),d7      | put difference in lower byte
                   1858: | if difference is too large we don't shift (actually, we can just exit) '
                   1859:        cmpw    IMM (FLT_MANT_DIG+2),d7         
                   1860:        bge     Laddsf$b$small
                   1861:        cmpw    IMM (16),d7     | if difference >= 16 swap
                   1862:        bge     4f
                   1863: 2:
                   1864:        subw    IMM (1),d7
                   1865: 3:     lsrl    IMM (1),d2      | shift right second operand
                   1866:        roxrl   IMM (1),d3
                   1867:        dbra    d7,3b
                   1868:        bra     Laddsf$3
                   1869: 4:
                   1870:        movew   d2,d3
                   1871:        swap    d3
                   1872:        movew   d3,d2
                   1873:        swap    d2
                   1874:        subw    IMM (16),d7
                   1875:        bne     2b              | if still more bits, go back to normal case
                   1876:        bra     Laddsf$3
                   1877: 5:
                   1878:        exg     d6,d7           | exchange the exponents
                   1879:        subl    d6,d7           | keep the largest exponent
                   1880:        negl    d7              |
                   1881:        lsrw    IMM (8),d7      | put difference in lower byte
                   1882: | if difference is too large we don't shift (and exit!) '
                   1883:        cmpw    IMM (FLT_MANT_DIG+2),d7         
                   1884:        bge     Laddsf$a$small
                   1885:        cmpw    IMM (16),d7     | if difference >= 16 swap
                   1886:        bge     8f
                   1887: 6:
                   1888:        subw    IMM (1),d7
                   1889: 7:     lsrl    IMM (1),d0      | shift right first operand
                   1890:        roxrl   IMM (1),d1
                   1891:        dbra    d7,7b
                   1892:        bra     Laddsf$3
                   1893: 8:
                   1894:        movew   d0,d1
                   1895:        swap    d1
                   1896:        movew   d1,d0
                   1897:        swap    d0
                   1898:        subw    IMM (16),d7
                   1899:        bne     6b              | if still more bits, go back to normal case
                   1900:                                | otherwise we fall through
                   1901: 
                   1902: | Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the
                   1903: | signs are stored in a0 and a1).
                   1904: 
                   1905: Laddsf$3:
                   1906: | Here we have to decide whether to add or subtract the numbers
                   1907:        exg     d6,a0           | get signs back
                   1908:        exg     d7,a1           | and save the exponents
                   1909:        eorl    d6,d7           | combine sign bits
                   1910:        bmi     Lsubsf$0        | if negative a and b have opposite 
                   1911:                                | sign so we actually subtract the
                   1912:                                | numbers
                   1913: 
                   1914: | Here we have both positive or both negative
                   1915:        exg     d6,a0           | now we have the exponent in d6
                   1916:        movel   a0,d7           | and sign in d7
                   1917:        andl    IMM (0x80000000),d7
                   1918: | Here we do the addition.
                   1919:        addl    d3,d1
                   1920:        addxl   d2,d0
                   1921: | Note: now we have d2, d3, d4 and d5 to play with! 
                   1922: 
                   1923: | Put the exponent, in the first byte, in d2, to use the "standard" rounding
                   1924: | routines:
                   1925:        movel   d6,d2
                   1926:        lsrw    IMM (8),d2
                   1927: 
                   1928: | Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider
                   1929: | the case of denormalized numbers in the rounding routine itself).
                   1930: | As in the addition (not in the subtraction!) we could have set 
                   1931: | one more bit we check this:
                   1932:        btst    IMM (FLT_MANT_DIG+1),d0 
                   1933:        beq     1f
                   1934:        lsrl    IMM (1),d0
                   1935:        roxrl   IMM (1),d1
                   1936:        addl    IMM (1),d2
                   1937: 1:
                   1938:        lea     Laddsf$4,a0     | to return from rounding routine
                   1939:        lea     SYM (_fpCCR),a1 | check the rounding mode
                   1940:        movew   a1@(6),d6       | rounding mode in d6
                   1941:        beq     Lround$to$nearest
                   1942:        cmpw    IMM (ROUND_TO_PLUS),d6
                   1943:        bhi     Lround$to$minus
                   1944:        blt     Lround$to$zero
                   1945:        bra     Lround$to$plus
                   1946: Laddsf$4:
                   1947: | Put back the exponent, but check for overflow.
                   1948:        cmpw    IMM (0xff),d2
                   1949:        bhi     1f
                   1950:        bclr    IMM (FLT_MANT_DIG-1),d0
                   1951:        lslw    IMM (7),d2
                   1952:        swap    d2
                   1953:        orl     d2,d0
                   1954:        bra     Laddsf$ret
                   1955: 1:
                   1956:        movew   IMM (ADD),d5
                   1957:        bra     Lf$overflow
                   1958: 
                   1959: Lsubsf$0:
                   1960: | We are here if a > 0 and b < 0 (sign bits cleared).
                   1961: | Here we do the subtraction.
                   1962:        movel   d6,d7           | put sign in d7
                   1963:        andl    IMM (0x80000000),d7
                   1964: 
                   1965:        subl    d3,d1           | result in d0-d1
                   1966:        subxl   d2,d0           |
                   1967:        beq     Laddsf$ret      | if zero just exit
                   1968:        bpl     1f              | if positive skip the following
                   1969:        bchg    IMM (31),d7     | change sign bit in d7
                   1970:        negl    d1
                   1971:        negxl   d0
                   1972: 1:
                   1973:        exg     d2,a0           | now we have the exponent in d2
                   1974:        lsrw    IMM (8),d2      | put it in the first byte
                   1975: 
                   1976: | Now d0-d1 is positive and the sign bit is in d7.
                   1977: 
                   1978: | Note that we do not have to normalize, since in the subtraction bit
                   1979: | #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by
                   1980: | the rounding routines themselves.
                   1981:        lea     Lsubsf$1,a0     | to return from rounding routine
                   1982:        lea     SYM (_fpCCR),a1 | check the rounding mode
                   1983:        movew   a1@(6),d6       | rounding mode in d6
                   1984:        beq     Lround$to$nearest
                   1985:        cmpw    IMM (ROUND_TO_PLUS),d6
                   1986:        bhi     Lround$to$minus
                   1987:        blt     Lround$to$zero
                   1988:        bra     Lround$to$plus
                   1989: Lsubsf$1:
                   1990: | Put back the exponent (we can't have overflow!). '
                   1991:        bclr    IMM (FLT_MANT_DIG-1),d0
                   1992:        lslw    IMM (7),d2
                   1993:        swap    d2
                   1994:        orl     d2,d0
                   1995:        bra     Laddsf$ret
                   1996: 
                   1997: | If one of the numbers was too small (difference of exponents >= 
                   1998: | FLT_MANT_DIG+2) we return the other (and now we don't have to '
                   1999: | check for finiteness or zero).
                   2000: Laddsf$a$small:
                   2001:        movel   a6@(12),d0
                   2002:        lea     SYM (_fpCCR),a0
                   2003:        movew   IMM (0),a0@
                   2004:        moveml  sp@+,d2-d7      | restore data registers
                   2005:        unlk    a6              | and return
                   2006:        rts
                   2007: 
                   2008: Laddsf$b$small:
                   2009:        movel   a6@(8),d0
                   2010:        lea     SYM (_fpCCR),a0
                   2011:        movew   IMM (0),a0@
                   2012:        moveml  sp@+,d2-d7      | restore data registers
                   2013:        unlk    a6              | and return
                   2014:        rts
                   2015: 
                   2016: | If the numbers are denormalized remember to put exponent equal to 1.
                   2017: 
                   2018: Laddsf$a$den:
                   2019:        movel   d5,d6           | d5 contains 0x01000000
                   2020:        swap    d6
                   2021:        bra     Laddsf$1
                   2022: 
                   2023: Laddsf$b$den:
                   2024:        movel   d5,d7
                   2025:        swap    d7
                   2026:        notl    d4              | make d4 into a mask for the fraction
                   2027:                                | (this was not executed after the jump)
                   2028:        bra     Laddsf$2
                   2029: 
                   2030: | The rest is mainly code for the different results which can be 
                   2031: | returned (checking always for +/-INFINITY and NaN).
                   2032: 
                   2033: Laddsf$b:
                   2034: | Return b (if a is zero).
                   2035:        movel   a6@(12),d0
                   2036:        bra     1f
                   2037: Laddsf$a:
                   2038: | Return a (if b is zero).
                   2039:        movel   a6@(8),d0
                   2040: 1:
                   2041:        movew   IMM (ADD),d5
                   2042: | We have to check for NaN and +/-infty.
                   2043:        movel   d0,d7
                   2044:        andl    IMM (0x80000000),d7     | put sign in d7
                   2045:        bclr    IMM (31),d0             | clear sign
                   2046:        cmpl    IMM (INFINITY),d0       | check for infty or NaN
                   2047:        bge     2f
                   2048:        movel   d0,d0           | check for zero (we do this because we don't '
                   2049:        bne     Laddsf$ret      | want to return -0 by mistake
                   2050:        bclr    IMM (31),d7     | if zero be sure to clear sign
                   2051:        bra     Laddsf$ret      | if everything OK just return
                   2052: 2:
                   2053: | The value to be returned is either +/-infty or NaN
                   2054:        andl    IMM (0x007fffff),d0     | check for NaN
                   2055:        bne     Lf$inop                 | if mantissa not zero is NaN
                   2056:        bra     Lf$infty
                   2057: 
                   2058: Laddsf$ret:
                   2059: | Normal exit (a and b nonzero, result is not NaN nor +/-infty).
                   2060: | We have to clear the exception flags (just the exception type).
                   2061:        lea     SYM (_fpCCR),a0
                   2062:        movew   IMM (0),a0@
                   2063:        orl     d7,d0           | put sign bit
                   2064:        moveml  sp@+,d2-d7      | restore data registers
                   2065:        unlk    a6              | and return
                   2066:        rts
                   2067: 
                   2068: Laddsf$ret$den:
                   2069: | Return a denormalized number (for addition we don't signal underflow) '
                   2070:        lsrl    IMM (1),d0      | remember to shift right back once
                   2071:        bra     Laddsf$ret      | and return
                   2072: 
                   2073: | Note: when adding two floats of the same sign if either one is 
                   2074: | NaN we return NaN without regard to whether the other is finite or 
                   2075: | not. When subtracting them (i.e., when adding two numbers of 
                   2076: | opposite signs) things are more complicated: if both are INFINITY 
                   2077: | we return NaN, if only one is INFINITY and the other is NaN we return
                   2078: | NaN, but if it is finite we return INFINITY with the corresponding sign.
                   2079: 
                   2080: Laddsf$nf:
                   2081:        movew   IMM (ADD),d5
                   2082: | This could be faster but it is not worth the effort, since it is not
                   2083: | executed very often. We sacrifice speed for clarity here.
                   2084:        movel   a6@(8),d0       | get the numbers back (remember that we
                   2085:        movel   a6@(12),d1      | did some processing already)
                   2086:        movel   IMM (INFINITY),d4 | useful constant (INFINITY)
                   2087:        movel   d0,d2           | save sign bits
                   2088:        movel   d1,d3
                   2089:        bclr    IMM (31),d0     | clear sign bits
                   2090:        bclr    IMM (31),d1
                   2091: | We know that one of them is either NaN of +/-INFINITY
                   2092: | Check for NaN (if either one is NaN return NaN)
                   2093:        cmpl    d4,d0           | check first a (d0)
                   2094:        bhi     Lf$inop         
                   2095:        cmpl    d4,d1           | check now b (d1)
                   2096:        bhi     Lf$inop         
                   2097: | Now comes the check for +/-INFINITY. We know that both are (maybe not
                   2098: | finite) numbers, but we have to check if both are infinite whether we
                   2099: | are adding or subtracting them.
                   2100:        eorl    d3,d2           | to check sign bits
                   2101:        bmi     1f
                   2102:        movel   d0,d7
                   2103:        andl    IMM (0x80000000),d7     | get (common) sign bit
                   2104:        bra     Lf$infty
                   2105: 1:
                   2106: | We know one (or both) are infinite, so we test for equality between the
                   2107: | two numbers (if they are equal they have to be infinite both, so we
                   2108: | return NaN).
                   2109:        cmpl    d1,d0           | are both infinite?
                   2110:        beq     Lf$inop         | if so return NaN
                   2111: 
                   2112:        movel   d0,d7
                   2113:        andl    IMM (0x80000000),d7 | get a's sign bit '
                   2114:        cmpl    d4,d0           | test now for infinity
                   2115:        beq     Lf$infty        | if a is INFINITY return with this sign
                   2116:        bchg    IMM (31),d7     | else we know b is INFINITY and has
                   2117:        bra     Lf$infty        | the opposite sign
                   2118: 
                   2119: |=============================================================================
                   2120: |                             __mulsf3
                   2121: |=============================================================================
                   2122: 
                   2123: | float __mulsf3(float, float);
                   2124: SYM (__mulsf3):
                   2125:        link    a6,IMM (0)
                   2126:        moveml  d2-d7,sp@-
                   2127:        movel   a6@(8),d0       | get a into d0
                   2128:        movel   a6@(12),d1      | and b into d1
                   2129:        movel   d0,d7           | d7 will hold the sign of the product
                   2130:        eorl    d1,d7           |
                   2131:        andl    IMM (0x80000000),d7
                   2132:        movel   IMM (INFINITY),d6       | useful constant (+INFINITY)
                   2133:        movel   d6,d5                   | another (mask for fraction)
                   2134:        notl    d5                      |
                   2135:        movel   IMM (0x00800000),d4     | this is to put hidden bit back
                   2136:        bclr    IMM (31),d0             | get rid of a's sign bit '
                   2137:        movel   d0,d2                   |
                   2138:        beq     Lmulsf$a$0              | branch if a is zero
                   2139:        bclr    IMM (31),d1             | get rid of b's sign bit '
                   2140:        movel   d1,d3           |
                   2141:        beq     Lmulsf$b$0      | branch if b is zero
                   2142:        cmpl    d6,d0           | is a big?
                   2143:        bhi     Lmulsf$inop     | if a is NaN return NaN
                   2144:        beq     Lmulsf$inf      | if a is INFINITY we have to check b
                   2145:        cmpl    d6,d1           | now compare b with INFINITY
                   2146:        bhi     Lmulsf$inop     | is b NaN?
                   2147:        beq     Lmulsf$overflow | is b INFINITY?
                   2148: | Here we have both numbers finite and nonzero (and with no sign bit).
                   2149: | Now we get the exponents into d2 and d3.
                   2150:        andl    d6,d2           | and isolate exponent in d2
                   2151:        beq     Lmulsf$a$den    | if exponent is zero we have a denormalized
                   2152:        andl    d5,d0           | and isolate fraction
                   2153:        orl     d4,d0           | and put hidden bit back
                   2154:        swap    d2              | I like exponents in the first byte
                   2155:        lsrw    IMM (7),d2      | 
                   2156: Lmulsf$1:                      | number
                   2157:        andl    d6,d3           |
                   2158:        beq     Lmulsf$b$den    |
                   2159:        andl    d5,d1           |
                   2160:        orl     d4,d1           |
                   2161:        swap    d3              |
                   2162:        lsrw    IMM (7),d3      |
                   2163: Lmulsf$2:                      |
                   2164:        addw    d3,d2           | add exponents
                   2165:        subw    IMM (F_BIAS+1),d2 | and subtract bias (plus one)
                   2166: 
                   2167: | We are now ready to do the multiplication. The situation is as follows:
                   2168: | both a and b have bit FLT_MANT_DIG-1 set (even if they were 
                   2169: | denormalized to start with!), which means that in the product 
                   2170: | bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the 
                   2171: | high long) is set. 
                   2172: 
                   2173: | To do the multiplication let us move the number a little bit around ...
                   2174:        movel   d1,d6           | second operand in d6
                   2175:        movel   d0,d5           | first operand in d4-d5
                   2176:        movel   IMM (0),d4
                   2177:        movel   d4,d1           | the sums will go in d0-d1
                   2178:        movel   d4,d0
                   2179: 
                   2180: | now bit FLT_MANT_DIG-1 becomes bit 31:
                   2181:        lsll    IMM (31-FLT_MANT_DIG+1),d6              
                   2182: 
                   2183: | Start the loop (we loop #FLT_MANT_DIG times):
                   2184:        movew   IMM (FLT_MANT_DIG-1),d3 
                   2185: 1:     addl    d1,d1           | shift sum 
                   2186:        addxl   d0,d0
                   2187:        lsll    IMM (1),d6      | get bit bn
                   2188:        bcc     2f              | if not set skip sum
                   2189:        addl    d5,d1           | add a
                   2190:        addxl   d4,d0
                   2191: 2:     dbf     d3,1b           | loop back
                   2192: 
                   2193: | Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG
                   2194: | (mod 32) of d0 set. The first thing to do now is to normalize it so bit 
                   2195: | FLT_MANT_DIG is set (to do the rounding).
                   2196:        rorl    IMM (6),d1
                   2197:        swap    d1
                   2198:        movew   d1,d3
                   2199:        andw    IMM (0x03ff),d3
                   2200:        andw    IMM (0xfd00),d1
                   2201:        lsll    IMM (8),d0
                   2202:        addl    d0,d0
                   2203:        addl    d0,d0
                   2204:        orw     d3,d0
                   2205: 
                   2206:        movew   IMM (MULTIPLY),d5
                   2207:        
                   2208:        btst    IMM (FLT_MANT_DIG+1),d0
                   2209:        beq     Lround$exit
                   2210:        lsrl    IMM (1),d0
                   2211:        roxrl   IMM (1),d1
                   2212:        addw    IMM (1),d2
                   2213:        bra     Lround$exit
                   2214: 
                   2215: Lmulsf$inop:
                   2216:        movew   IMM (MULTIPLY),d5
                   2217:        bra     Lf$inop
                   2218: 
                   2219: Lmulsf$overflow:
                   2220:        movew   IMM (MULTIPLY),d5
                   2221:        bra     Lf$overflow
                   2222: 
                   2223: Lmulsf$inf:
                   2224:        movew   IMM (MULTIPLY),d5
                   2225: | If either is NaN return NaN; else both are (maybe infinite) numbers, so
                   2226: | return INFINITY with the correct sign (which is in d7).
                   2227:        cmpl    d6,d1           | is b NaN?
                   2228:        bhi     Lf$inop         | if so return NaN
                   2229:        bra     Lf$overflow     | else return +/-INFINITY
                   2230: 
                   2231: | If either number is zero return zero, unless the other is +/-INFINITY, 
                   2232: | or NaN, in which case we return NaN.
                   2233: Lmulsf$b$0:
                   2234: | Here d1 (==b) is zero.
                   2235:        movel   d1,d0           | put b into d0 (just a zero)
                   2236:        movel   a6@(8),d1       | get a again to check for non-finiteness
                   2237:        bra     1f
                   2238: Lmulsf$a$0:
                   2239:        movel   a6@(12),d1      | get b again to check for non-finiteness
                   2240: 1:     bclr    IMM (31),d1     | clear sign bit 
                   2241:        cmpl    IMM (INFINITY),d1 | and check for a large exponent
                   2242:        bge     Lf$inop         | if b is +/-INFINITY or NaN return NaN
                   2243:        lea     SYM (_fpCCR),a0 | else return zero
                   2244:        movew   IMM (0),a0@     | 
                   2245:        moveml  sp@+,d2-d7      | 
                   2246:        unlk    a6              | 
                   2247:        rts                     | 
                   2248: 
                   2249: | If a number is denormalized we put an exponent of 1 but do not put the 
                   2250: | hidden bit back into the fraction; instead we shift left until bit 23
                   2251: | (the hidden bit) is set, adjusting the exponent accordingly. We do this
                   2252: | to ensure that the product of the fractions is close to 1.
                   2253: Lmulsf$a$den:
                   2254:        movel   IMM (1),d2
                   2255:        andl    d5,d0
                   2256: 1:     addl    d0,d0           | shift a left (until bit 23 is set)
                   2257:        subw    IMM (1),d2      | and adjust exponent
                   2258:        btst    IMM (FLT_MANT_DIG-1),d0
                   2259:        bne     Lmulsf$1        |
                   2260:        bra     1b              | else loop back
                   2261: 
                   2262: Lmulsf$b$den:
                   2263:        movel   IMM (1),d3
                   2264:        andl    d5,d1
                   2265: 1:     addl    d1,d1           | shift b left until bit 23 is set
                   2266:        subw    IMM (1),d3      | and adjust exponent
                   2267:        btst    IMM (FLT_MANT_DIG-1),d1
                   2268:        bne     Lmulsf$2        |
                   2269:        bra     1b              | else loop back
                   2270: 
                   2271: |=============================================================================
                   2272: |                             __divsf3
                   2273: |=============================================================================
                   2274: 
                   2275: | float __divsf3(float, float);
                   2276: SYM (__divsf3):
                   2277:        link    a6,IMM (0)
                   2278:        moveml  d2-d7,sp@-
                   2279:        movel   a6@(8),d0               | get a into d0
                   2280:        movel   a6@(12),d1              | and b into d1
                   2281:        movel   d0,d7                   | d7 will hold the sign of the result
                   2282:        eorl    d1,d7                   |
                   2283:        andl    IMM (0x80000000),d7     | 
                   2284:        movel   IMM (INFINITY),d6       | useful constant (+INFINITY)
                   2285:        movel   d6,d5                   | another (mask for fraction)
                   2286:        notl    d5                      |
                   2287:        movel   IMM (0x00800000),d4     | this is to put hidden bit back
                   2288:        bclr    IMM (31),d0             | get rid of a's sign bit '
                   2289:        movel   d0,d2                   |
                   2290:        beq     Ldivsf$a$0              | branch if a is zero
                   2291:        bclr    IMM (31),d1             | get rid of b's sign bit '
                   2292:        movel   d1,d3                   |
                   2293:        beq     Ldivsf$b$0              | branch if b is zero
                   2294:        cmpl    d6,d0                   | is a big?
                   2295:        bhi     Ldivsf$inop             | if a is NaN return NaN
                   2296:        beq     Ldivsf$inf              | if a is INFINITY we have to check b
                   2297:        cmpl    d6,d1                   | now compare b with INFINITY 
                   2298:        bhi     Ldivsf$inop             | if b is NaN return NaN
                   2299:        beq     Ldivsf$underflow
                   2300: | Here we have both numbers finite and nonzero (and with no sign bit).
                   2301: | Now we get the exponents into d2 and d3 and normalize the numbers to
                   2302: | ensure that the ratio of the fractions is close to 1. We do this by
                   2303: | making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set.
                   2304:        andl    d6,d2           | and isolate exponent in d2
                   2305:        beq     Ldivsf$a$den    | if exponent is zero we have a denormalized
                   2306:        andl    d5,d0           | and isolate fraction
                   2307:        orl     d4,d0           | and put hidden bit back
                   2308:        swap    d2              | I like exponents in the first byte
                   2309:        lsrw    IMM (7),d2      | 
                   2310: Ldivsf$1:                      | 
                   2311:        andl    d6,d3           |
                   2312:        beq     Ldivsf$b$den    |
                   2313:        andl    d5,d1           |
                   2314:        orl     d4,d1           |
                   2315:        swap    d3              |
                   2316:        lsrw    IMM (7),d3      |
                   2317: Ldivsf$2:                      |
                   2318:        subw    d3,d2           | subtract exponents
                   2319:        addw    IMM (F_BIAS),d2 | and add bias
                   2320:  
                   2321: | We are now ready to do the division. We have prepared things in such a way
                   2322: | that the ratio of the fractions will be less than 2 but greater than 1/2.
                   2323: | At this point the registers in use are:
                   2324: | d0   holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1)
                   2325: | d1   holds b (second operand, bit FLT_MANT_DIG=1)
                   2326: | d2   holds the difference of the exponents, corrected by the bias
                   2327: | d7   holds the sign of the ratio
                   2328: | d4, d5, d6 hold some constants
                   2329:        movel   d7,a0           | d6-d7 will hold the ratio of the fractions
                   2330:        movel   IMM (0),d6      | 
                   2331:        movel   d6,d7
                   2332: 
                   2333:        movew   IMM (FLT_MANT_DIG+1),d3
                   2334: 1:     cmpl    d0,d1           | is a < b?
                   2335:        bhi     2f              |
                   2336:        bset    d3,d6           | set a bit in d6
                   2337:        subl    d1,d0           | if a >= b  a <-- a-b
                   2338:        beq     3f              | if a is zero, exit
                   2339: 2:     addl    d0,d0           | multiply a by 2
                   2340:        dbra    d3,1b
                   2341: 
                   2342: | Now we keep going to set the sticky bit ...
                   2343:        movew   IMM (FLT_MANT_DIG),d3
                   2344: 1:     cmpl    d0,d1
                   2345:        ble     2f
                   2346:        addl    d0,d0
                   2347:        dbra    d3,1b
                   2348:        movel   IMM (0),d1
                   2349:        bra     3f
                   2350: 2:     movel   IMM (0),d1
                   2351:        subw    IMM (FLT_MANT_DIG),d3
                   2352:        addw    IMM (31),d3
                   2353:        bset    d3,d1
                   2354: 3:
                   2355:        movel   d6,d0           | put the ratio in d0-d1
                   2356:        movel   a0,d7           | get sign back
                   2357: 
                   2358: | Because of the normalization we did before we are guaranteed that 
                   2359: | d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set,
                   2360: | bit 25 could be set, and if it is not set then bit 24 is necessarily set.
                   2361:        btst    IMM (FLT_MANT_DIG+1),d0         
                   2362:        beq     1f              | if it is not set, then bit 24 is set
                   2363:        lsrl    IMM (1),d0      |
                   2364:        addw    IMM (1),d2      |
                   2365: 1:
                   2366: | Now round, check for over- and underflow, and exit.
                   2367:        movew   IMM (DIVIDE),d5
                   2368:        bra     Lround$exit
                   2369: 
                   2370: Ldivsf$inop:
                   2371:        movew   IMM (DIVIDE),d5
                   2372:        bra     Lf$inop
                   2373: 
                   2374: Ldivsf$overflow:
                   2375:        movew   IMM (DIVIDE),d5
                   2376:        bra     Lf$overflow
                   2377: 
                   2378: Ldivsf$underflow:
                   2379:        movew   IMM (DIVIDE),d5
                   2380:        bra     Lf$underflow
                   2381: 
                   2382: Ldivsf$a$0:
                   2383:        movew   IMM (DIVIDE),d5
                   2384: | If a is zero check to see whether b is zero also. In that case return
                   2385: | NaN; then check if b is NaN, and return NaN also in that case. Else
                   2386: | return zero.
                   2387:        andl    IMM (0x7fffffff),d1     | clear sign bit and test b
                   2388:        beq     Lf$inop                 | if b is also zero return NaN
                   2389:        cmpl    IMM (INFINITY),d1       | check for NaN
                   2390:        bhi     Lf$inop                 | 
                   2391:        movel   IMM (0),d0              | else return zero
                   2392:        lea     SYM (_fpCCR),a0         |
                   2393:        movew   IMM (0),a0@             |
                   2394:        moveml  sp@+,d2-d7              | 
                   2395:        unlk    a6                      | 
                   2396:        rts                             | 
                   2397:        
                   2398: Ldivsf$b$0:
                   2399:        movew   IMM (DIVIDE),d5
                   2400: | If we got here a is not zero. Check if a is NaN; in that case return NaN,
                   2401: | else return +/-INFINITY. Remember that a is in d0 with the sign bit 
                   2402: | cleared already.
                   2403:        cmpl    IMM (INFINITY),d0       | compare d0 with INFINITY
                   2404:        bhi     Lf$inop                 | if larger it is NaN
                   2405:        bra     Lf$div$0                | else signal DIVIDE_BY_ZERO
                   2406: 
                   2407: Ldivsf$inf:
                   2408:        movew   IMM (DIVIDE),d5
                   2409: | If a is INFINITY we have to check b
                   2410:        cmpl    IMM (INFINITY),d1       | compare b with INFINITY 
                   2411:        bge     Lf$inop                 | if b is NaN or INFINITY return NaN
                   2412:        bra     Lf$overflow             | else return overflow
                   2413: 
                   2414: | If a number is denormalized we put an exponent of 1 but do not put the 
                   2415: | bit back into the fraction.
                   2416: Ldivsf$a$den:
                   2417:        movel   IMM (1),d2
                   2418:        andl    d5,d0
                   2419: 1:     addl    d0,d0           | shift a left until bit FLT_MANT_DIG-1 is set
                   2420:        subw    IMM (1),d2      | and adjust exponent
                   2421:        btst    IMM (FLT_MANT_DIG-1),d0
                   2422:        bne     Ldivsf$1
                   2423:        bra     1b
                   2424: 
                   2425: Ldivsf$b$den:
                   2426:        movel   IMM (1),d3
                   2427:        andl    d5,d1
                   2428: 1:     addl    d1,d1           | shift b left until bit FLT_MANT_DIG is set
                   2429:        subw    IMM (1),d3      | and adjust exponent
                   2430:        btst    IMM (FLT_MANT_DIG-1),d1
                   2431:        bne     Ldivsf$2
                   2432:        bra     1b
                   2433: 
                   2434: Lround$exit:
                   2435: | This is a common exit point for __mulsf3 and __divsf3. 
                   2436: 
                   2437: | First check for underlow in the exponent:
                   2438:        cmpw    IMM (-FLT_MANT_DIG-1),d2                
                   2439:        blt     Lf$underflow    
                   2440: | It could happen that the exponent is less than 1, in which case the 
                   2441: | number is denormalized. In this case we shift right and adjust the 
                   2442: | exponent until it becomes 1 or the fraction is zero (in the latter case 
                   2443: | we signal underflow and return zero).
                   2444:        movel   IMM (0),d6      | d6 is used temporarily
                   2445:        cmpw    IMM (1),d2      | if the exponent is less than 1 we 
                   2446:        bge     2f              | have to shift right (denormalize)
                   2447: 1:     addw    IMM (1),d2      | adjust the exponent
                   2448:        lsrl    IMM (1),d0      | shift right once 
                   2449:        roxrl   IMM (1),d1      |
                   2450:        roxrl   IMM (1),d6      | d6 collect bits we would lose otherwise
                   2451:        cmpw    IMM (1),d2      | is the exponent 1 already?
                   2452:        beq     2f              | if not loop back
                   2453:        bra     1b              |
                   2454:        bra     Lf$underflow    | safety check, shouldn't execute '
                   2455: 2:     orl     d6,d1           | this is a trick so we don't lose  '
                   2456:                                | the extra bits which were flushed right
                   2457: | Now call the rounding routine (which takes care of denormalized numbers):
                   2458:        lea     Lround$0,a0     | to return from rounding routine
                   2459:        lea     SYM (_fpCCR),a1 | check the rounding mode
                   2460:        movew   a1@(6),d6       | rounding mode in d6
                   2461:        beq     Lround$to$nearest
                   2462:        cmpw    IMM (ROUND_TO_PLUS),d6
                   2463:        bhi     Lround$to$minus
                   2464:        blt     Lround$to$zero
                   2465:        bra     Lround$to$plus
                   2466: Lround$0:
                   2467: | Here we have a correctly rounded result (either normalized or denormalized).
                   2468: 
                   2469: | Here we should have either a normalized number or a denormalized one, and
                   2470: | the exponent is necessarily larger or equal to 1 (so we don't have to  '
                   2471: | check again for underflow!). We have to check for overflow or for a 
                   2472: | denormalized number (which also signals underflow).
                   2473: | Check for overflow (i.e., exponent >= 255).
                   2474:        cmpw    IMM (0x00ff),d2
                   2475:        bge     Lf$overflow
                   2476: | Now check for a denormalized number (exponent==0).
                   2477:        movew   d2,d2
                   2478:        beq     Lf$den
                   2479: 1:
                   2480: | Put back the exponents and sign and return.
                   2481:        lslw    IMM (7),d2      | exponent back to fourth byte
                   2482:        bclr    IMM (FLT_MANT_DIG-1),d0
                   2483:        swap    d0              | and put back exponent
                   2484:        orw     d2,d0           | 
                   2485:        swap    d0              |
                   2486:        orl     d7,d0           | and sign also
                   2487: 
                   2488:        lea     SYM (_fpCCR),a0
                   2489:        movew   IMM (0),a0@
                   2490:        moveml  sp@+,d2-d7
                   2491:        unlk    a6
                   2492:        rts
                   2493: 
                   2494: |=============================================================================
                   2495: |                             __negsf2
                   2496: |=============================================================================
                   2497: 
                   2498: | This is trivial and could be shorter if we didn't bother checking for NaN '
                   2499: | and +/-INFINITY.
                   2500: 
                   2501: | float __negsf2(float);
                   2502: SYM (__negsf2):
                   2503:        link    a6,IMM (0)
                   2504:        moveml  d2-d7,sp@-
                   2505:        movew   IMM (NEGATE),d5
                   2506:        movel   a6@(8),d0       | get number to negate in d0
                   2507:        bchg    IMM (31),d0     | negate
                   2508:        movel   d0,d1           | make a positive copy
                   2509:        bclr    IMM (31),d1     |
                   2510:        tstl    d1              | check for zero
                   2511:        beq     2f              | if zero (either sign) return +zero
                   2512:        cmpl    IMM (INFINITY),d1 | compare to +INFINITY
                   2513:        blt     1f              |
                   2514:        bhi     Lf$inop         | if larger (fraction not zero) is NaN
                   2515:        movel   d0,d7           | else get sign and return INFINITY
                   2516:        andl    IMM (0x80000000),d7
                   2517:        bra     Lf$infty                
                   2518: 1:     lea     SYM (_fpCCR),a0
                   2519:        movew   IMM (0),a0@
                   2520:        moveml  sp@+,d2-d7
                   2521:        unlk    a6
                   2522:        rts
                   2523: 2:     bclr    IMM (31),d0
                   2524:        bra     1b
                   2525: 
                   2526: |=============================================================================
                   2527: |                             __cmpsf2
                   2528: |=============================================================================
                   2529: 
                   2530: GREATER =  1
                   2531: LESS    = -1
                   2532: EQUAL   =  0
                   2533: 
                   2534: | int __cmpsf2(float, float);
                   2535: SYM (__cmpsf2):
                   2536:        link    a6,IMM (0)
                   2537:        moveml  d2-d7,sp@-      | save registers
                   2538:        movew   IMM (COMPARE),d5
                   2539:        movel   a6@(8),d0       | get first operand
                   2540:        movel   a6@(12),d1      | get second operand
                   2541: | Check if either is NaN, and in that case return garbage and signal
                   2542: | INVALID_OPERATION. Check also if either is zero, and clear the signs
                   2543: | if necessary.
                   2544:        movel   d0,d6
                   2545:        andl    IMM (0x7fffffff),d0
                   2546:        beq     Lcmpsf$a$0
                   2547:        cmpl    IMM (0x7f800000),d0
                   2548:        bhi     Lf$inop
                   2549: Lcmpsf$1:
                   2550:        movel   d1,d7
                   2551:        andl    IMM (0x7fffffff),d1
                   2552:        beq     Lcmpsf$b$0
                   2553:        cmpl    IMM (0x7f800000),d1
                   2554:        bhi     Lf$inop
                   2555: Lcmpsf$2:
                   2556: | Check the signs
                   2557:        eorl    d6,d7
                   2558:        bpl     1f
                   2559: | If the signs are not equal check if a >= 0
                   2560:        tstl    d6
                   2561:        bpl     Lcmpsf$a$gt$b   | if (a >= 0 && b < 0) => a > b
                   2562:        bmi     Lcmpsf$b$gt$a   | if (a < 0 && b >= 0) => a < b
                   2563: 1:
                   2564: | If the signs are equal check for < 0
                   2565:        tstl    d6
                   2566:        bpl     1f
                   2567: | If both are negative exchange them
                   2568:        exg     d0,d1
                   2569: 1:
                   2570: | Now that they are positive we just compare them as longs (does this also
                   2571: | work for denormalized numbers?).
                   2572:        cmpl    d0,d1
                   2573:        bhi     Lcmpsf$b$gt$a   | |b| > |a|
                   2574:        bne     Lcmpsf$a$gt$b   | |b| < |a|
                   2575: | If we got here a == b.
                   2576:        movel   IMM (EQUAL),d0
                   2577:        moveml  sp@+,d2-d7      | put back the registers
                   2578:        unlk    a6
                   2579:        rts
                   2580: Lcmpsf$a$gt$b:
                   2581:        movel   IMM (GREATER),d0
                   2582:        moveml  sp@+,d2-d7      | put back the registers
                   2583:        unlk    a6
                   2584:        rts
                   2585: Lcmpsf$b$gt$a:
                   2586:        movel   IMM (LESS),d0
                   2587:        moveml  sp@+,d2-d7      | put back the registers
                   2588:        unlk    a6
                   2589:        rts
                   2590: 
                   2591: Lcmpsf$a$0:    
                   2592:        bclr    IMM (31),d6
                   2593:        bra     Lcmpsf$1
                   2594: Lcmpsf$b$0:
                   2595:        bclr    IMM (31),d7
                   2596:        bra     Lcmpsf$2
                   2597: 
                   2598: |=============================================================================
                   2599: |                           rounding routines
                   2600: |=============================================================================
                   2601: 
                   2602: | The rounding routines expect the number to be normalized in registers
                   2603: | d0-d1, with the exponent in register d2. They assume that the 
                   2604: | exponent is larger or equal to 1. They return a properly normalized number
                   2605: | if possible, and a denormalized number otherwise. The exponent is returned
                   2606: | in d2.
                   2607: 
                   2608: Lround$to$nearest:
                   2609: | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
                   2610: | Here we assume that the exponent is not too small (this should be checked
                   2611: | before entering the rounding routine), but the number could be denormalized.
                   2612: 
                   2613: | Check for denormalized numbers:
                   2614: 1:     btst    IMM (FLT_MANT_DIG),d0
                   2615:        bne     2f              | if set the number is normalized
                   2616: | Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent 
                   2617: | is one (remember that a denormalized number corresponds to an 
                   2618: | exponent of -F_BIAS+1).
                   2619:        cmpw    IMM (1),d2      | remember that the exponent is at least one
                   2620:        beq     2f              | an exponent of one means denormalized
                   2621:        addl    d1,d1           | else shift and adjust the exponent
                   2622:        addxl   d0,d0           |
                   2623:        dbra    d2,1b           |
                   2624: 2:
                   2625: | Now round: we do it as follows: after the shifting we can write the
                   2626: | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
                   2627: | If delta < 1, do nothing. If delta > 1, add 1 to f. 
                   2628: | If delta == 1, we make sure the rounded number will be even (odd?) 
                   2629: | (after shifting).
                   2630:        btst    IMM (0),d0      | is delta < 1?
                   2631:        beq     2f              | if so, do not do anything
                   2632:        tstl    d1              | is delta == 1?
                   2633:        bne     1f              | if so round to even
                   2634:        movel   d0,d1           | 
                   2635:        andl    IMM (2),d1      | bit 1 is the last significant bit
                   2636:        addl    d1,d0           | 
                   2637:        bra     2f              | 
                   2638: 1:     movel   IMM (1),d1      | else add 1 
                   2639:        addl    d1,d0           |
                   2640: | Shift right once (because we used bit #FLT_MANT_DIG!).
                   2641: 2:     lsrl    IMM (1),d0              
                   2642: | Now check again bit #FLT_MANT_DIG (rounding could have produced a
                   2643: | 'fraction overflow' ...).
                   2644:        btst    IMM (FLT_MANT_DIG),d0   
                   2645:        beq     1f
                   2646:        lsrl    IMM (1),d0
                   2647:        addw    IMM (1),d2
                   2648: 1:
                   2649: | If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we 
                   2650: | have to put the exponent to zero and return a denormalized number.
                   2651:        btst    IMM (FLT_MANT_DIG-1),d0
                   2652:        beq     1f
                   2653:        jmp     a0@
                   2654: 1:     movel   IMM (0),d2
                   2655:        jmp     a0@
                   2656: 
                   2657: Lround$to$zero:
                   2658: Lround$to$plus:
                   2659: Lround$to$minus:
                   2660:        jmp     a0@
                   2661: #endif /* L_float */
                   2662: 
                   2663: | gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2,
                   2664: | __ledf2, __ltdf2 to all return the same value as a direct call to
                   2665: | __cmpdf2 would.  In this implementation, each of these routines
                   2666: | simply calls __cmpdf2.  It would be more efficient to give the
                   2667: | __cmpdf2 routine several names, but separating them out will make it
                   2668: | easier to write efficient versions of these routines someday.
                   2669: 
                   2670: #ifdef  L_eqdf2
                   2671: LL0:
                   2672:        .text
                   2673:        .proc
                   2674: |#PROC# 04
                   2675:        LF18    =       4
                   2676:        LS18    =       128
                   2677:        LFF18   =       0
                   2678:        LSS18   =       0
                   2679:        LV18    =       0
                   2680:        .text
                   2681:        .globl  SYM (__eqdf2)
                   2682: SYM (__eqdf2):
                   2683: |#PROLOGUE# 0
                   2684:        link    a6,IMM (0)
                   2685: |#PROLOGUE# 1
                   2686:        movl    a6@(20),sp@-
                   2687:        movl    a6@(16),sp@-
                   2688:        movl    a6@(12),sp@-
                   2689:        movl    a6@(8),sp@-
                   2690:        jbsr    SYM (__cmpdf2)
                   2691: |#PROLOGUE# 2
                   2692:        unlk    a6
                   2693: |#PROLOGUE# 3
                   2694:        rts
                   2695: #endif /* L_eqdf2 */
                   2696: 
                   2697: #ifdef  L_nedf2
                   2698: LL0:
                   2699:        .text
                   2700:        .proc
                   2701: |#PROC# 04
                   2702:        LF18    =       8
                   2703:        LS18    =       132
                   2704:        LFF18   =       0
                   2705:        LSS18   =       0
                   2706:        LV18    =       0
                   2707:        .text
                   2708:        .globl  SYM (__nedf2)
                   2709: SYM (__nedf2):
                   2710: |#PROLOGUE# 0
                   2711:        link    a6,IMM (0)
                   2712: |#PROLOGUE# 1
                   2713:        movl    a6@(20),sp@-
                   2714:        movl    a6@(16),sp@-
                   2715:        movl    a6@(12),sp@-
                   2716:        movl    a6@(8),sp@-
                   2717:        jbsr    SYM (__cmpdf2)
                   2718: |#PROLOGUE# 2
                   2719:        unlk    a6
                   2720: |#PROLOGUE# 3
                   2721:        rts
                   2722: #endif /* L_nedf2 */
                   2723: 
                   2724: #ifdef  L_gtdf2
                   2725:        .text
                   2726:        .proc
                   2727: |#PROC# 04
                   2728:        LF18    =       8
                   2729:        LS18    =       132
                   2730:        LFF18   =       0
                   2731:        LSS18   =       0
                   2732:        LV18    =       0
                   2733:        .text
                   2734:        .globl  SYM (__gtdf2)
                   2735: SYM (__gtdf2):
                   2736: |#PROLOGUE# 0
                   2737:        link    a6,IMM (0)
                   2738: |#PROLOGUE# 1
                   2739:        movl    a6@(20),sp@-
                   2740:        movl    a6@(16),sp@-
                   2741:        movl    a6@(12),sp@-
                   2742:        movl    a6@(8),sp@-
                   2743:        jbsr    SYM (__cmpdf2)
                   2744: |#PROLOGUE# 2
                   2745:        unlk    a6
                   2746: |#PROLOGUE# 3
                   2747:        rts
                   2748: #endif /* L_gtdf2 */
                   2749: 
                   2750: #ifdef  L_gedf2
                   2751: LL0:
                   2752:        .text
                   2753:        .proc
                   2754: |#PROC# 04
                   2755:        LF18    =       8
                   2756:        LS18    =       132
                   2757:        LFF18   =       0
                   2758:        LSS18   =       0
                   2759:        LV18    =       0
                   2760:        .text
                   2761:        .globl  SYM (__gedf2)
                   2762: SYM (__gedf2):
                   2763: |#PROLOGUE# 0
                   2764:        link    a6,IMM (0)
                   2765: |#PROLOGUE# 1
                   2766:        movl    a6@(20),sp@-
                   2767:        movl    a6@(16),sp@-
                   2768:        movl    a6@(12),sp@-
                   2769:        movl    a6@(8),sp@-
                   2770:        jbsr    SYM (__cmpdf2)
                   2771: |#PROLOGUE# 2
                   2772:        unlk    a6
                   2773: |#PROLOGUE# 3
                   2774:        rts
                   2775: #endif /* L_gedf2 */
                   2776: 
                   2777: #ifdef  L_ltdf2
                   2778: LL0:
                   2779:        .text
                   2780:        .proc
                   2781: |#PROC# 04
                   2782:        LF18    =       8
                   2783:        LS18    =       132
                   2784:        LFF18   =       0
                   2785:        LSS18   =       0
                   2786:        LV18    =       0
                   2787:        .text
                   2788:        .globl  SYM (__ltdf2)
                   2789: SYM (__ltdf2):
                   2790: |#PROLOGUE# 0
                   2791:        link    a6,IMM (0)
                   2792: |#PROLOGUE# 1
                   2793:        movl    a6@(20),sp@-
                   2794:        movl    a6@(16),sp@-
                   2795:        movl    a6@(12),sp@-
                   2796:        movl    a6@(8),sp@-
                   2797:        jbsr    SYM (__cmpdf2)
                   2798: |#PROLOGUE# 2
                   2799:        unlk    a6
                   2800: |#PROLOGUE# 3
                   2801:        rts
                   2802: #endif /* L_ltdf2 */
                   2803: 
                   2804: #ifdef  L_ledf2
                   2805:        .text
                   2806:        .proc
                   2807: |#PROC# 04
                   2808:        LF18    =       8
                   2809:        LS18    =       132
                   2810:        LFF18   =       0
                   2811:        LSS18   =       0
                   2812:        LV18    =       0
                   2813:        .text
                   2814:        .globl  SYM (__ledf2)
                   2815: SYM (__ledf2):
                   2816: |#PROLOGUE# 0
                   2817:        link    a6,IMM (0)
                   2818: |#PROLOGUE# 1
                   2819:        movl    a6@(20),sp@-
                   2820:        movl    a6@(16),sp@-
                   2821:        movl    a6@(12),sp@-
                   2822:        movl    a6@(8),sp@-
                   2823:        jbsr    SYM (__cmpdf2)
                   2824: |#PROLOGUE# 2
                   2825:        unlk    a6
                   2826: |#PROLOGUE# 3
                   2827:        rts
                   2828: #endif /* L_ledf2 */
                   2829: 
                   2830: | The comments above about __eqdf2, et. al., also apply to __eqsf2,
                   2831: | et. al., except that the latter call __cmpsf2 rather than __cmpdf2.
                   2832: 
                   2833: #ifdef  L_eqsf2
                   2834:        .text
                   2835:        .proc
                   2836: |#PROC# 04
                   2837:        LF18    =       4
                   2838:        LS18    =       128
                   2839:        LFF18   =       0
                   2840:        LSS18   =       0
                   2841:        LV18    =       0
                   2842:        .text
                   2843:        .globl  SYM (__eqsf2)
                   2844: SYM (__eqsf2):
                   2845: |#PROLOGUE# 0
                   2846:        link    a6,IMM (0)
                   2847: |#PROLOGUE# 1
                   2848:        movl    a6@(12),sp@-
                   2849:        movl    a6@(8),sp@-
                   2850:        jbsr    SYM (__cmpsf2)
                   2851: |#PROLOGUE# 2
                   2852:        unlk    a6
                   2853: |#PROLOGUE# 3
                   2854:        rts
                   2855: #endif /* L_eqsf2 */
                   2856: 
                   2857: #ifdef  L_nesf2
                   2858:        .text
                   2859:        .proc
                   2860: |#PROC# 04
                   2861:        LF18    =       8
                   2862:        LS18    =       132
                   2863:        LFF18   =       0
                   2864:        LSS18   =       0
                   2865:        LV18    =       0
                   2866:        .text
                   2867:        .globl  SYM (__nesf2)
                   2868: SYM (__nesf2):
                   2869: |#PROLOGUE# 0
                   2870:        link    a6,IMM (0)
                   2871: |#PROLOGUE# 1
                   2872:        movl    a6@(12),sp@-
                   2873:        movl    a6@(8),sp@-
                   2874:        jbsr    SYM (__cmpsf2)
                   2875: |#PROLOGUE# 2
                   2876:        unlk    a6
                   2877: |#PROLOGUE# 3
                   2878:        rts
                   2879: #endif /* L_nesf2 */
                   2880: 
                   2881: #ifdef  L_gtsf2
                   2882:        .text
                   2883:        .proc
                   2884: |#PROC# 04
                   2885:        LF18    =       8
                   2886:        LS18    =       132
                   2887:        LFF18   =       0
                   2888:        LSS18   =       0
                   2889:        LV18    =       0
                   2890:        .text
                   2891:        .globl  SYM (__gtsf2)
                   2892: SYM (__gtsf2):
                   2893: |#PROLOGUE# 0
                   2894:        link    a6,IMM (0)
                   2895: |#PROLOGUE# 1
                   2896:        movl    a6@(12),sp@-
                   2897:        movl    a6@(8),sp@-
                   2898:        jbsr    SYM (__cmpsf2)
                   2899: |#PROLOGUE# 2
                   2900:        unlk    a6
                   2901: |#PROLOGUE# 3
                   2902:        rts
                   2903: #endif /* L_gtsf2 */
                   2904: 
                   2905: #ifdef  L_gesf2
                   2906:        .text
                   2907:        .proc
                   2908: |#PROC# 04
                   2909:        LF18    =       8
                   2910:        LS18    =       132
                   2911:        LFF18   =       0
                   2912:        LSS18   =       0
                   2913:        LV18    =       0
                   2914:        .text
                   2915:        .globl  SYM (__gesf2)
                   2916: SYM (__gesf2):
                   2917: |#PROLOGUE# 0
                   2918:        link    a6,IMM (0)
                   2919: |#PROLOGUE# 1
                   2920:        movl    a6@(12),sp@-
                   2921:        movl    a6@(8),sp@-
                   2922:        jbsr    SYM (__cmpsf2)
                   2923: |#PROLOGUE# 2
                   2924:        unlk    a6
                   2925: |#PROLOGUE# 3
                   2926:        rts
                   2927: #endif /* L_gesf2 */
                   2928: 
                   2929: #ifdef  L_ltsf2
                   2930:        .text
                   2931:        .proc
                   2932: |#PROC# 04
                   2933:        LF18    =       8
                   2934:        LS18    =       132
                   2935:        LFF18   =       0
                   2936:        LSS18   =       0
                   2937:        LV18    =       0
                   2938:        .text
                   2939:        .globl  SYM (__ltsf2)
                   2940: SYM (__ltsf2):
                   2941: |#PROLOGUE# 0
                   2942:        link    a6,IMM (0)
                   2943: |#PROLOGUE# 1
                   2944:        movl    a6@(12),sp@-
                   2945:        movl    a6@(8),sp@-
                   2946:        jbsr    SYM (__cmpsf2)
                   2947: |#PROLOGUE# 2
                   2948:        unlk    a6
                   2949: |#PROLOGUE# 3
                   2950:        rts
                   2951: #endif /* L_ltsf2 */
                   2952: 
                   2953: #ifdef  L_lesf2
                   2954:        .text
                   2955:        .proc
                   2956: |#PROC# 04
                   2957:        LF18    =       8
                   2958:        LS18    =       132
                   2959:        LFF18   =       0
                   2960:        LSS18   =       0
                   2961:        LV18    =       0
                   2962:        .text
                   2963:        .globl  SYM (__lesf2)
                   2964: SYM (__lesf2):
                   2965: |#PROLOGUE# 0
                   2966:        link    a6,IMM (0)
                   2967: |#PROLOGUE# 1
                   2968:        movl    a6@(12),sp@-
                   2969:        movl    a6@(8),sp@-
                   2970:        jbsr    SYM (__cmpsf2)
                   2971: |#PROLOGUE# 2
                   2972:        unlk    a6
                   2973: |#PROLOGUE# 3
                   2974:        rts
                   2975: #endif /* L_lesf2 */
                   2976: 

unix.superglobalmegacorp.com

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