OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [m68k/] [lb1sf68.asm] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* libgcc routines for 68000 w/o floating-point hardware.
2
   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify it
7
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; either version 2, or (at your option) any
9
later version.
10
 
11
In addition to the permissions in the GNU General Public License, the
12
Free Software Foundation gives you unlimited permission to link the
13
compiled version of this file with other programs, and to distribute
14
those programs without any restriction coming from the use of this
15
file.  (The General Public License restrictions do apply in other
16
respects; for example, they cover modification of the file, and
17
distribution when not linked into another program.)
18
 
19
This file is distributed in the hope that it will be useful, but
20
WITHOUT ANY WARRANTY; without even the implied warranty of
21
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
General Public License for more details.
23
 
24
You should have received a copy of the GNU General Public License
25
along with this program; see the file COPYING.  If not, write to
26
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27
Boston, MA 02110-1301, USA.  */
28
 
29
/* As a special exception, if you link this library with files
30
   compiled with GCC to produce an executable, this does not cause
31
   the resulting executable to be covered by the GNU General Public License.
32
   This exception does not however invalidate any other reasons why
33
   the executable file might be covered by the GNU General Public License.  */
34
 
35
/* Use this one for any 680x0; assumes no floating point hardware.
36
   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
37
   Some of this code comes from MINIX, via the folks at ericsson.
38
   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
39
*/
40
 
41
/* These are predefined by new versions of GNU cpp.  */
42
 
43
#ifndef __USER_LABEL_PREFIX__
44
#define __USER_LABEL_PREFIX__ _
45
#endif
46
 
47
#ifndef __REGISTER_PREFIX__
48
#define __REGISTER_PREFIX__
49
#endif
50
 
51
#ifndef __IMMEDIATE_PREFIX__
52
#define __IMMEDIATE_PREFIX__ #
53
#endif
54
 
55
/* ANSI concatenation macros.  */
56
 
57
#define CONCAT1(a, b) CONCAT2(a, b)
58
#define CONCAT2(a, b) a ## b
59
 
60
/* Use the right prefix for global labels.  */
61
 
62
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
63
 
64
/* Use the right prefix for registers.  */
65
 
66
#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
67
 
68
/* Use the right prefix for immediate values.  */
69
 
70
#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
71
 
72
#define d0 REG (d0)
73
#define d1 REG (d1)
74
#define d2 REG (d2)
75
#define d3 REG (d3)
76
#define d4 REG (d4)
77
#define d5 REG (d5)
78
#define d6 REG (d6)
79
#define d7 REG (d7)
80
#define a0 REG (a0)
81
#define a1 REG (a1)
82
#define a2 REG (a2)
83
#define a3 REG (a3)
84
#define a4 REG (a4)
85
#define a5 REG (a5)
86
#define a6 REG (a6)
87
#define fp REG (fp)
88
#define sp REG (sp)
89
#define pc REG (pc)
90
 
91
/* Provide a few macros to allow for PIC code support.
92
 * With PIC, data is stored A5 relative so we've got to take a bit of special
93
 * care to ensure that all loads of global data is via A5.  PIC also requires
94
 * jumps and subroutine calls to be PC relative rather than absolute.  We cheat
95
 * a little on this and in the PIC case, we use short offset branches and
96
 * hope that the final object code is within range (which it should be).
97
 */
98
#ifndef __PIC__
99
 
100
        /* Non PIC (absolute/relocatable) versions */
101
 
102
        .macro PICCALL addr
103
        jbsr    \addr
104
        .endm
105
 
106
        .macro PICJUMP addr
107
        jmp     \addr
108
        .endm
109
 
110
        .macro PICLEA sym, reg
111
        lea     \sym, \reg
112
        .endm
113
 
114
        .macro PICPEA sym, areg
115
        pea     \sym
116
        .endm
117
 
118
#else /* __PIC__ */
119
 
120
        /* Common for -mid-shared-libary and -msep-data */
121
 
122
        .macro PICCALL addr
123
        bsr     \addr
124
        .endm
125
 
126
        .macro PICJUMP addr
127
        bra     \addr
128
        .endm
129
 
130
# if defined(__ID_SHARED_LIBRARY__)
131
 
132
        /* -mid-shared-library versions  */
133
 
134
        .macro PICLEA sym, reg
135
        movel   a5@(_current_shared_library_a5_offset_), \reg
136
        movel   \sym@GOT(\reg), \reg
137
        .endm
138
 
139
        .macro PICPEA sym, areg
140
        movel   a5@(_current_shared_library_a5_offset_), \areg
141
        movel   \sym@GOT(\areg), sp@-
142
        .endm
143
 
144
# else /* !__ID_SHARED_LIBRARY__ */
145
 
146
        /* Versions for -msep-data */
147
 
148
        .macro PICLEA sym, reg
149
        movel   \sym@GOT(a5), \reg
150
        .endm
151
 
152
        .macro PICPEA sym, areg
153
        movel   \sym@GOT(a5), sp@-
154
        .endm
155
 
156
# endif /* !__ID_SHARED_LIBRARY__ */
157
#endif /* __PIC__ */
158
 
159
 
160
#ifdef L_floatex
161
 
162
| This is an attempt at a decent floating point (single, double and
163
| extended double) code for the GNU C compiler. It should be easy to
164
| adapt to other compilers (but beware of the local labels!).
165
 
166
| Starting date: 21 October, 1990
167
 
168
| It is convenient to introduce the notation (s,e,f) for a floating point
169
| number, where s=sign, e=exponent, f=fraction. We will call a floating
170
| point number fpn to abbreviate, independently of the precision.
171
| Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023
172
| for doubles and 16383 for long doubles). We then have the following
173
| different cases:
174
|  1. Normalized fpns have 0 < e < MAX_EXP. They correspond to
175
|     (-1)^s x 1.f x 2^(e-bias-1).
176
|  2. Denormalized fpns have e=0. They correspond to numbers of the form
177
|     (-1)^s x 0.f x 2^(-bias).
178
|  3. +/-INFINITY have e=MAX_EXP, f=0.
179
|  4. Quiet NaN (Not a Number) have all bits set.
180
|  5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1.
181
 
182
|=============================================================================
183
|                                  exceptions
184
|=============================================================================
185
 
186
| This is the floating point condition code register (_fpCCR):
187
|
188
| struct {
189
|   short _exception_bits;
190
|   short _trap_enable_bits;
191
|   short _sticky_bits;
192
|   short _rounding_mode;
193
|   short _format;
194
|   short _last_operation;
195
|   union {
196
|     float sf;
197
|     double df;
198
|   } _operand1;
199
|   union {
200
|     float sf;
201
|     double df;
202
|   } _operand2;
203
| } _fpCCR;
204
 
205
        .data
206
        .even
207
 
208
        .globl  SYM (_fpCCR)
209
 
210
SYM (_fpCCR):
211
__exception_bits:
212
        .word   0
213
__trap_enable_bits:
214
        .word   0
215
__sticky_bits:
216
        .word   0
217
__rounding_mode:
218
        .word   ROUND_TO_NEAREST
219
__format:
220
        .word   NIL
221
__last_operation:
222
        .word   NOOP
223
__operand1:
224
        .long   0
225
        .long   0
226
__operand2:
227
        .long   0
228
        .long   0
229
 
230
| Offsets:
231
EBITS  = __exception_bits - SYM (_fpCCR)
232
TRAPE  = __trap_enable_bits - SYM (_fpCCR)
233
STICK  = __sticky_bits - SYM (_fpCCR)
234
ROUND  = __rounding_mode - SYM (_fpCCR)
235
FORMT  = __format - SYM (_fpCCR)
236
LASTO  = __last_operation - SYM (_fpCCR)
237
OPER1  = __operand1 - SYM (_fpCCR)
238
OPER2  = __operand2 - SYM (_fpCCR)
239
 
240
| The following exception types are supported:
241
INEXACT_RESULT          = 0x0001
242
UNDERFLOW               = 0x0002
243
OVERFLOW                = 0x0004
244
DIVIDE_BY_ZERO          = 0x0008
245
INVALID_OPERATION       = 0x0010
246
 
247
| The allowed rounding modes are:
248
UNKNOWN           = -1
249
ROUND_TO_NEAREST  = 0 | round result to nearest representable value
250
ROUND_TO_ZERO     = 1 | round result towards zero
251
ROUND_TO_PLUS     = 2 | round result towards plus infinity
252
ROUND_TO_MINUS    = 3 | round result towards minus infinity
253
 
254
| The allowed values of format are:
255
NIL          = 0
256
SINGLE_FLOAT = 1
257
DOUBLE_FLOAT = 2
258
LONG_FLOAT   = 3
259
 
260
| The allowed values for the last operation are:
261
NOOP         = 0
262
ADD          = 1
263
MULTIPLY     = 2
264
DIVIDE       = 3
265
NEGATE       = 4
266
COMPARE      = 5
267
EXTENDSFDF   = 6
268
TRUNCDFSF    = 7
269
 
270
|=============================================================================
271
|                           __clear_sticky_bits
272
|=============================================================================
273
 
274
| The sticky bits are normally not cleared (thus the name), whereas the
275
| exception type and exception value reflect the last computation.
276
| This routine is provided to clear them (you can also write to _fpCCR,
277
| since it is globally visible).
278
 
279
        .globl  SYM (__clear_sticky_bit)
280
 
281
        .text
282
        .even
283
 
284
| void __clear_sticky_bits(void);
285
SYM (__clear_sticky_bit):
286
        PICLEA  SYM (_fpCCR),a0
287
#ifndef __mcoldfire__
288
        movew   IMM (0),a0@(STICK)
289
#else
290
        clr.w   a0@(STICK)
291
#endif
292
        rts
293
 
294
|=============================================================================
295
|                           $_exception_handler
296
|=============================================================================
297
 
298
        .globl  $_exception_handler
299
 
300
        .text
301
        .even
302
 
303
| This is the common exit point if an exception occurs.
304
| NOTE: it is NOT callable from C!
305
| It expects the exception type in d7, the format (SINGLE_FLOAT,
306
| DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5.
307
| It sets the corresponding exception and sticky bits, and the format.
308
| Depending on the format if fills the corresponding slots for the
309
| operands which produced the exception (all this information is provided
310
| so if you write your own exception handlers you have enough information
311
| to deal with the problem).
312
| Then checks to see if the corresponding exception is trap-enabled,
313
| in which case it pushes the address of _fpCCR and traps through
314
| trap FPTRAP (15 for the moment).
315
 
316
FPTRAP = 15
317
 
318
$_exception_handler:
319
        PICLEA  SYM (_fpCCR),a0
320
        movew   d7,a0@(EBITS)   | set __exception_bits
321
#ifndef __mcoldfire__
322
        orw     d7,a0@(STICK)   | and __sticky_bits
323
#else
324
        movew   a0@(STICK),d4
325
        orl     d7,d4
326
        movew   d4,a0@(STICK)
327
#endif
328
        movew   d6,a0@(FORMT)   | and __format
329
        movew   d5,a0@(LASTO)   | and __last_operation
330
 
331
| Now put the operands in place:
332
#ifndef __mcoldfire__
333
        cmpw    IMM (SINGLE_FLOAT),d6
334
#else
335
        cmpl    IMM (SINGLE_FLOAT),d6
336
#endif
337
        beq     1f
338
        movel   a6@(8),a0@(OPER1)
339
        movel   a6@(12),a0@(OPER1+4)
340
        movel   a6@(16),a0@(OPER2)
341
        movel   a6@(20),a0@(OPER2+4)
342
        bra     2f
343
1:      movel   a6@(8),a0@(OPER1)
344
        movel   a6@(12),a0@(OPER2)
345
2:
346
| And check whether the exception is trap-enabled:
347
#ifndef __mcoldfire__
348
        andw    a0@(TRAPE),d7   | is exception trap-enabled?
349
#else
350
        clrl    d6
351
        movew   a0@(TRAPE),d6
352
        andl    d6,d7
353
#endif
354
        beq     1f              | no, exit
355
        PICPEA  SYM (_fpCCR),a1 | yes, push address of _fpCCR
356
        trap    IMM (FPTRAP)    | and trap
357
#ifndef __mcoldfire__
358
1:      moveml  sp@+,d2-d7      | restore data registers
359
#else
360
1:      moveml  sp@,d2-d7
361
        | XXX if frame pointer is ever removed, stack pointer must
362
        | be adjusted here.
363
#endif
364
        unlk    a6              | and return
365
        rts
366
#endif /* L_floatex */
367
 
368
#ifdef  L_mulsi3
369
        .text
370
        .proc
371
        .globl  SYM (__mulsi3)
372
SYM (__mulsi3):
373
        movew   sp@(4), d0      /* x0 -> d0 */
374
        muluw   sp@(10), d0     /* x0*y1 */
375
        movew   sp@(6), d1      /* x1 -> d1 */
376
        muluw   sp@(8), d1      /* x1*y0 */
377
#ifndef __mcoldfire__
378
        addw    d1, d0
379
#else
380
        addl    d1, d0
381
#endif
382
        swap    d0
383
        clrw    d0
384
        movew   sp@(6), d1      /* x1 -> d1 */
385
        muluw   sp@(10), d1     /* x1*y1 */
386
        addl    d1, d0
387
 
388
        rts
389
#endif /* L_mulsi3 */
390
 
391
#ifdef  L_udivsi3
392
        .text
393
        .proc
394
        .globl  SYM (__udivsi3)
395
SYM (__udivsi3):
396
#ifndef __mcoldfire__
397
        movel   d2, sp@-
398
        movel   sp@(12), d1     /* d1 = divisor */
399
        movel   sp@(8), d0      /* d0 = dividend */
400
 
401
        cmpl    IMM (0x10000), d1 /* divisor >= 2 ^ 16 ?   */
402
        jcc     L3              /* then try next algorithm */
403
        movel   d0, d2
404
        clrw    d2
405
        swap    d2
406
        divu    d1, d2          /* high quotient in lower word */
407
        movew   d2, d0          /* save high quotient */
408
        swap    d0
409
        movew   sp@(10), d2     /* get low dividend + high rest */
410
        divu    d1, d2          /* low quotient */
411
        movew   d2, d0
412
        jra     L6
413
 
414
L3:     movel   d1, d2          /* use d2 as divisor backup */
415
L4:     lsrl    IMM (1), d1     /* shift divisor */
416
        lsrl    IMM (1), d0     /* shift dividend */
417
        cmpl    IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ?  */
418
        jcc     L4
419
        divu    d1, d0          /* now we have 16-bit divisor */
420
        andl    IMM (0xffff), d0 /* mask out divisor, ignore remainder */
421
 
422
/* Multiply the 16-bit tentative quotient with the 32-bit divisor.  Because of
423
   the operand ranges, this might give a 33-bit product.  If this product is
424
   greater than the dividend, the tentative quotient was too large. */
425
        movel   d2, d1
426
        mulu    d0, d1          /* low part, 32 bits */
427
        swap    d2
428
        mulu    d0, d2          /* high part, at most 17 bits */
429
        swap    d2              /* align high part with low part */
430
        tstw    d2              /* high part 17 bits? */
431
        jne     L5              /* if 17 bits, quotient was too large */
432
        addl    d2, d1          /* add parts */
433
        jcs     L5              /* if sum is 33 bits, quotient was too large */
434
        cmpl    sp@(8), d1      /* compare the sum with the dividend */
435
        jls     L6              /* if sum > dividend, quotient was too large */
436
L5:     subql   IMM (1), d0     /* adjust quotient */
437
 
438
L6:     movel   sp@+, d2
439
        rts
440
 
441
#else /* __mcoldfire__ */
442
 
443
/* ColdFire implementation of non-restoring division algorithm from
444
   Hennessy & Patterson, Appendix A. */
445
        link    a6,IMM (-12)
446
        moveml  d2-d4,sp@
447
        movel   a6@(8),d0
448
        movel   a6@(12),d1
449
        clrl    d2              | clear p
450
        moveq   IMM (31),d4
451
L1:     addl    d0,d0           | shift reg pair (p,a) one bit left
452
        addxl   d2,d2
453
        movl    d2,d3           | subtract b from p, store in tmp.
454
        subl    d1,d3
455
        jcs     L2              | if no carry,
456
        bset    IMM (0),d0      | set the low order bit of a to 1,
457
        movl    d3,d2           | and store tmp in p.
458
L2:     subql   IMM (1),d4
459
        jcc     L1
460
        moveml  sp@,d2-d4       | restore data registers
461
        unlk    a6              | and return
462
        rts
463
#endif /* __mcoldfire__ */
464
 
465
#endif /* L_udivsi3 */
466
 
467
#ifdef  L_divsi3
468
        .text
469
        .proc
470
        .globl  SYM (__divsi3)
471
SYM (__divsi3):
472
        movel   d2, sp@-
473
 
474
        moveq   IMM (1), d2     /* sign of result stored in d2 (=1 or =-1) */
475
        movel   sp@(12), d1     /* d1 = divisor */
476
        jpl     L1
477
        negl    d1
478
#ifndef __mcoldfire__
479
        negb    d2              /* change sign because divisor <0  */
480
#else
481
        negl    d2              /* change sign because divisor <0  */
482
#endif
483
L1:     movel   sp@(8), d0      /* d0 = dividend */
484
        jpl     L2
485
        negl    d0
486
#ifndef __mcoldfire__
487
        negb    d2
488
#else
489
        negl    d2
490
#endif
491
 
492
L2:     movel   d1, sp@-
493
        movel   d0, sp@-
494
        PICCALL SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */
495
        addql   IMM (8), sp
496
 
497
        tstb    d2
498
        jpl     L3
499
        negl    d0
500
 
501
L3:     movel   sp@+, d2
502
        rts
503
#endif /* L_divsi3 */
504
 
505
#ifdef  L_umodsi3
506
        .text
507
        .proc
508
        .globl  SYM (__umodsi3)
509
SYM (__umodsi3):
510
        movel   sp@(8), d1      /* d1 = divisor */
511
        movel   sp@(4), d0      /* d0 = dividend */
512
        movel   d1, sp@-
513
        movel   d0, sp@-
514
        PICCALL SYM (__udivsi3)
515
        addql   IMM (8), sp
516
        movel   sp@(8), d1      /* d1 = divisor */
517
#ifndef __mcoldfire__
518
        movel   d1, sp@-
519
        movel   d0, sp@-
520
        PICCALL SYM (__mulsi3)  /* d0 = (a/b)*b */
521
        addql   IMM (8), sp
522
#else
523
        mulsl   d1,d0
524
#endif
525
        movel   sp@(4), d1      /* d1 = dividend */
526
        subl    d0, d1          /* d1 = a - (a/b)*b */
527
        movel   d1, d0
528
        rts
529
#endif /* L_umodsi3 */
530
 
531
#ifdef  L_modsi3
532
        .text
533
        .proc
534
        .globl  SYM (__modsi3)
535
SYM (__modsi3):
536
        movel   sp@(8), d1      /* d1 = divisor */
537
        movel   sp@(4), d0      /* d0 = dividend */
538
        movel   d1, sp@-
539
        movel   d0, sp@-
540
        PICCALL SYM (__divsi3)
541
        addql   IMM (8), sp
542
        movel   sp@(8), d1      /* d1 = divisor */
543
#ifndef __mcoldfire__
544
        movel   d1, sp@-
545
        movel   d0, sp@-
546
        PICCALL SYM (__mulsi3)  /* d0 = (a/b)*b */
547
        addql   IMM (8), sp
548
#else
549
        mulsl   d1,d0
550
#endif
551
        movel   sp@(4), d1      /* d1 = dividend */
552
        subl    d0, d1          /* d1 = a - (a/b)*b */
553
        movel   d1, d0
554
        rts
555
#endif /* L_modsi3 */
556
 
557
 
558
#ifdef  L_double
559
 
560
        .globl  SYM (_fpCCR)
561
        .globl  $_exception_handler
562
 
563
QUIET_NaN      = 0xffffffff
564
 
565
D_MAX_EXP      = 0x07ff
566
D_BIAS         = 1022
567
DBL_MAX_EXP    = D_MAX_EXP - D_BIAS
568
DBL_MIN_EXP    = 1 - D_BIAS
569
DBL_MANT_DIG   = 53
570
 
571
INEXACT_RESULT          = 0x0001
572
UNDERFLOW               = 0x0002
573
OVERFLOW                = 0x0004
574
DIVIDE_BY_ZERO          = 0x0008
575
INVALID_OPERATION       = 0x0010
576
 
577
DOUBLE_FLOAT = 2
578
 
579
NOOP         = 0
580
ADD          = 1
581
MULTIPLY     = 2
582
DIVIDE       = 3
583
NEGATE       = 4
584
COMPARE      = 5
585
EXTENDSFDF   = 6
586
TRUNCDFSF    = 7
587
 
588
UNKNOWN           = -1
589
ROUND_TO_NEAREST  = 0 | round result to nearest representable value
590
ROUND_TO_ZERO     = 1 | round result towards zero
591
ROUND_TO_PLUS     = 2 | round result towards plus infinity
592
ROUND_TO_MINUS    = 3 | round result towards minus infinity
593
 
594
| Entry points:
595
 
596
        .globl SYM (__adddf3)
597
        .globl SYM (__subdf3)
598
        .globl SYM (__muldf3)
599
        .globl SYM (__divdf3)
600
        .globl SYM (__negdf2)
601
        .globl SYM (__cmpdf2)
602
        .globl SYM (__cmpdf2_internal)
603
 
604
        .text
605
        .even
606
 
607
| These are common routines to return and signal exceptions.
608
 
609
Ld$den:
610
| Return and signal a denormalized number
611
        orl     d7,d0
612
        movew   IMM (INEXACT_RESULT+UNDERFLOW),d7
613
        moveq   IMM (DOUBLE_FLOAT),d6
614
        PICJUMP $_exception_handler
615
 
616
Ld$infty:
617
Ld$overflow:
618
| Return a properly signed INFINITY and set the exception flags
619
        movel   IMM (0x7ff00000),d0
620
        movel   IMM (0),d1
621
        orl     d7,d0
622
        movew   IMM (INEXACT_RESULT+OVERFLOW),d7
623
        moveq   IMM (DOUBLE_FLOAT),d6
624
        PICJUMP $_exception_handler
625
 
626
Ld$underflow:
627
| Return 0 and set the exception flags
628
        movel   IMM (0),d0
629
        movel   d0,d1
630
        movew   IMM (INEXACT_RESULT+UNDERFLOW),d7
631
        moveq   IMM (DOUBLE_FLOAT),d6
632
        PICJUMP $_exception_handler
633
 
634
Ld$inop:
635
| Return a quiet NaN and set the exception flags
636
        movel   IMM (QUIET_NaN),d0
637
        movel   d0,d1
638
        movew   IMM (INEXACT_RESULT+INVALID_OPERATION),d7
639
        moveq   IMM (DOUBLE_FLOAT),d6
640
        PICJUMP $_exception_handler
641
 
642
Ld$div$0:
643
| Return a properly signed INFINITY and set the exception flags
644
        movel   IMM (0x7ff00000),d0
645
        movel   IMM (0),d1
646
        orl     d7,d0
647
        movew   IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
648
        moveq   IMM (DOUBLE_FLOAT),d6
649
        PICJUMP $_exception_handler
650
 
651
|=============================================================================
652
|=============================================================================
653
|                         double precision routines
654
|=============================================================================
655
|=============================================================================
656
 
657
| A double precision floating point number (double) has the format:
658
|
659
| struct _double {
660
|  unsigned int sign      : 1;  /* sign bit */
661
|  unsigned int exponent  : 11; /* exponent, shifted by 126 */
662
|  unsigned int fraction  : 52; /* fraction */
663
| } double;
664
|
665
| Thus sizeof(double) = 8 (64 bits).
666
|
667
| All the routines are callable from C programs, and return the result
668
| in the register pair d0-d1. They also preserve all registers except
669
| d0-d1 and a0-a1.
670
 
671
|=============================================================================
672
|                              __subdf3
673
|=============================================================================
674
 
675
| double __subdf3(double, double);
676
SYM (__subdf3):
677
        bchg    IMM (31),sp@(12) | change sign of second operand
678
                                | and fall through, so we always add
679
|=============================================================================
680
|                              __adddf3
681
|=============================================================================
682
 
683
| double __adddf3(double, double);
684
SYM (__adddf3):
685
#ifndef __mcoldfire__
686
        link    a6,IMM (0)      | everything will be done in registers
687
        moveml  d2-d7,sp@-      | save all data registers and a2 (but d0-d1)
688
#else
689
        link    a6,IMM (-24)
690
        moveml  d2-d7,sp@
691
#endif
692
        movel   a6@(8),d0       | get first operand
693
        movel   a6@(12),d1      |
694
        movel   a6@(16),d2      | get second operand
695
        movel   a6@(20),d3      |
696
 
697
        movel   d0,d7           | get d0's sign bit in d7 '
698
        addl    d1,d1           | check and clear sign bit of a, and gain one
699
        addxl   d0,d0           | bit of extra precision
700
        beq     Ladddf$b        | if zero return second operand
701
 
702
        movel   d2,d6           | save sign in d6
703
        addl    d3,d3           | get rid of sign bit and gain one bit of
704
        addxl   d2,d2           | extra precision
705
        beq     Ladddf$a        | if zero return first operand
706
 
707
        andl    IMM (0x80000000),d7 | isolate a's sign bit '
708
        swap    d6              | and also b's sign bit '
709
#ifndef __mcoldfire__
710
        andw    IMM (0x8000),d6 |
711
        orw     d6,d7           | and combine them into d7, so that a's sign '
712
                                | bit is in the high word and b's is in the '
713
                                | low word, so d6 is free to be used
714
#else
715
        andl    IMM (0x8000),d6
716
        orl     d6,d7
717
#endif
718
        movel   d7,a0           | now save d7 into a0, so d7 is free to
719
                                | be used also
720
 
721
| Get the exponents and check for denormalized and/or infinity.
722
 
723
        movel   IMM (0x001fffff),d6 | mask for the fraction
724
        movel   IMM (0x00200000),d7 | mask to put hidden bit back
725
 
726
        movel   d0,d4           |
727
        andl    d6,d0           | get fraction in d0
728
        notl    d6              | make d6 into mask for the exponent
729
        andl    d6,d4           | get exponent in d4
730
        beq     Ladddf$a$den    | branch if a is denormalized
731
        cmpl    d6,d4           | check for INFINITY or NaN
732
        beq     Ladddf$nf       |
733
        orl     d7,d0           | and put hidden bit back
734
Ladddf$1:
735
        swap    d4              | shift right exponent so that it starts
736
#ifndef __mcoldfire__
737
        lsrw    IMM (5),d4      | in bit 0 and not bit 20
738
#else
739
        lsrl    IMM (5),d4      | in bit 0 and not bit 20
740
#endif
741
| Now we have a's exponent in d4 and fraction in d0-d1 '
742
        movel   d2,d5           | save b to get exponent
743
        andl    d6,d5           | get exponent in d5
744
        beq     Ladddf$b$den    | branch if b is denormalized
745
        cmpl    d6,d5           | check for INFINITY or NaN
746
        beq     Ladddf$nf
747
        notl    d6              | make d6 into mask for the fraction again
748
        andl    d6,d2           | and get fraction in d2
749
        orl     d7,d2           | and put hidden bit back
750
Ladddf$2:
751
        swap    d5              | shift right exponent so that it starts
752
#ifndef __mcoldfire__
753
        lsrw    IMM (5),d5      | in bit 0 and not bit 20
754
#else
755
        lsrl    IMM (5),d5      | in bit 0 and not bit 20
756
#endif
757
 
758
| Now we have b's exponent in d5 and fraction in d2-d3. '
759
 
760
| The situation now is as follows: the signs are combined in a0, the
761
| numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a)
762
| and d5 (b). To do the rounding correctly we need to keep all the
763
| bits until the end, so we need to use d0-d1-d2-d3 for the first number
764
| and d4-d5-d6-d7 for the second. To do this we store (temporarily) the
765
| exponents in a2-a3.
766
 
767
#ifndef __mcoldfire__
768
        moveml  a2-a3,sp@-      | save the address registers
769
#else
770
        movel   a2,sp@-
771
        movel   a3,sp@-
772
        movel   a4,sp@-
773
#endif
774
 
775
        movel   d4,a2           | save the exponents
776
        movel   d5,a3           |
777
 
778
        movel   IMM (0),d7      | and move the numbers around
779
        movel   d7,d6           |
780
        movel   d3,d5           |
781
        movel   d2,d4           |
782
        movel   d7,d3           |
783
        movel   d7,d2           |
784
 
785
| Here we shift the numbers until the exponents are the same, and put
786
| the largest exponent in a2.
787
#ifndef __mcoldfire__
788
        exg     d4,a2           | get exponents back
789
        exg     d5,a3           |
790
        cmpw    d4,d5           | compare the exponents
791
#else
792
        movel   d4,a4           | get exponents back
793
        movel   a2,d4
794
        movel   a4,a2
795
        movel   d5,a4
796
        movel   a3,d5
797
        movel   a4,a3
798
        cmpl    d4,d5           | compare the exponents
799
#endif
800
        beq     Ladddf$3        | if equal don't shift '
801
        bhi     9f              | branch if second exponent is higher
802
 
803
| Here we have a's exponent larger than b's, so we have to shift b. We do
804
| this by using as counter d2:
805
1:      movew   d4,d2           | move largest exponent to d2
806
#ifndef __mcoldfire__
807
        subw    d5,d2           | and subtract second exponent
808
        exg     d4,a2           | get back the longs we saved
809
        exg     d5,a3           |
810
#else
811
        subl    d5,d2           | and subtract second exponent
812
        movel   d4,a4           | get back the longs we saved
813
        movel   a2,d4
814
        movel   a4,a2
815
        movel   d5,a4
816
        movel   a3,d5
817
        movel   a4,a3
818
#endif
819
| if difference is too large we don't shift (actually, we can just exit) '
820
#ifndef __mcoldfire__
821
        cmpw    IMM (DBL_MANT_DIG+2),d2
822
#else
823
        cmpl    IMM (DBL_MANT_DIG+2),d2
824
#endif
825
        bge     Ladddf$b$small
826
#ifndef __mcoldfire__
827
        cmpw    IMM (32),d2     | if difference >= 32, shift by longs
828
#else
829
        cmpl    IMM (32),d2     | if difference >= 32, shift by longs
830
#endif
831
        bge     5f
832
2:
833
#ifndef __mcoldfire__
834
        cmpw    IMM (16),d2     | if difference >= 16, shift by words
835
#else
836
        cmpl    IMM (16),d2     | if difference >= 16, shift by words
837
#endif
838
        bge     6f
839
        bra     3f              | enter dbra loop
840
 
841
4:
842
#ifndef __mcoldfire__
843
        lsrl    IMM (1),d4
844
        roxrl   IMM (1),d5
845
        roxrl   IMM (1),d6
846
        roxrl   IMM (1),d7
847
#else
848
        lsrl    IMM (1),d7
849
        btst    IMM (0),d6
850
        beq     10f
851
        bset    IMM (31),d7
852
10:     lsrl    IMM (1),d6
853
        btst    IMM (0),d5
854
        beq     11f
855
        bset    IMM (31),d6
856
11:     lsrl    IMM (1),d5
857
        btst    IMM (0),d4
858
        beq     12f
859
        bset    IMM (31),d5
860
12:     lsrl    IMM (1),d4
861
#endif
862
3:
863
#ifndef __mcoldfire__
864
        dbra    d2,4b
865
#else
866
        subql   IMM (1),d2
867
        bpl     4b
868
#endif
869
        movel   IMM (0),d2
870
        movel   d2,d3
871
        bra     Ladddf$4
872
5:
873
        movel   d6,d7
874
        movel   d5,d6
875
        movel   d4,d5
876
        movel   IMM (0),d4
877
#ifndef __mcoldfire__
878
        subw    IMM (32),d2
879
#else
880
        subl    IMM (32),d2
881
#endif
882
        bra     2b
883
6:
884
        movew   d6,d7
885
        swap    d7
886
        movew   d5,d6
887
        swap    d6
888
        movew   d4,d5
889
        swap    d5
890
        movew   IMM (0),d4
891
        swap    d4
892
#ifndef __mcoldfire__
893
        subw    IMM (16),d2
894
#else
895
        subl    IMM (16),d2
896
#endif
897
        bra     3b
898
 
899
9:
900
#ifndef __mcoldfire__
901
        exg     d4,d5
902
        movew   d4,d6
903
        subw    d5,d6           | keep d5 (largest exponent) in d4
904
        exg     d4,a2
905
        exg     d5,a3
906
#else
907
        movel   d5,d6
908
        movel   d4,d5
909
        movel   d6,d4
910
        subl    d5,d6
911
        movel   d4,a4
912
        movel   a2,d4
913
        movel   a4,a2
914
        movel   d5,a4
915
        movel   a3,d5
916
        movel   a4,a3
917
#endif
918
| if difference is too large we don't shift (actually, we can just exit) '
919
#ifndef __mcoldfire__
920
        cmpw    IMM (DBL_MANT_DIG+2),d6
921
#else
922
        cmpl    IMM (DBL_MANT_DIG+2),d6
923
#endif
924
        bge     Ladddf$a$small
925
#ifndef __mcoldfire__
926
        cmpw    IMM (32),d6     | if difference >= 32, shift by longs
927
#else
928
        cmpl    IMM (32),d6     | if difference >= 32, shift by longs
929
#endif
930
        bge     5f
931
2:
932
#ifndef __mcoldfire__
933
        cmpw    IMM (16),d6     | if difference >= 16, shift by words
934
#else
935
        cmpl    IMM (16),d6     | if difference >= 16, shift by words
936
#endif
937
        bge     6f
938
        bra     3f              | enter dbra loop
939
 
940
4:
941
#ifndef __mcoldfire__
942
        lsrl    IMM (1),d0
943
        roxrl   IMM (1),d1
944
        roxrl   IMM (1),d2
945
        roxrl   IMM (1),d3
946
#else
947
        lsrl    IMM (1),d3
948
        btst    IMM (0),d2
949
        beq     10f
950
        bset    IMM (31),d3
951
10:     lsrl    IMM (1),d2
952
        btst    IMM (0),d1
953
        beq     11f
954
        bset    IMM (31),d2
955
11:     lsrl    IMM (1),d1
956
        btst    IMM (0),d0
957
        beq     12f
958
        bset    IMM (31),d1
959
12:     lsrl    IMM (1),d0
960
#endif
961
3:
962
#ifndef __mcoldfire__
963
        dbra    d6,4b
964
#else
965
        subql   IMM (1),d6
966
        bpl     4b
967
#endif
968
        movel   IMM (0),d7
969
        movel   d7,d6
970
        bra     Ladddf$4
971
5:
972
        movel   d2,d3
973
        movel   d1,d2
974
        movel   d0,d1
975
        movel   IMM (0),d0
976
#ifndef __mcoldfire__
977
        subw    IMM (32),d6
978
#else
979
        subl    IMM (32),d6
980
#endif
981
        bra     2b
982
6:
983
        movew   d2,d3
984
        swap    d3
985
        movew   d1,d2
986
        swap    d2
987
        movew   d0,d1
988
        swap    d1
989
        movew   IMM (0),d0
990
        swap    d0
991
#ifndef __mcoldfire__
992
        subw    IMM (16),d6
993
#else
994
        subl    IMM (16),d6
995
#endif
996
        bra     3b
997
Ladddf$3:
998
#ifndef __mcoldfire__
999
        exg     d4,a2
1000
        exg     d5,a3
1001
#else
1002
        movel   d4,a4
1003
        movel   a2,d4
1004
        movel   a4,a2
1005
        movel   d5,a4
1006
        movel   a3,d5
1007
        movel   a4,a3
1008
#endif
1009
Ladddf$4:
1010
| Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and
1011
| the signs in a4.
1012
 
1013
| Here we have to decide whether to add or subtract the numbers:
1014
#ifndef __mcoldfire__
1015
        exg     d7,a0           | get the signs
1016
        exg     d6,a3           | a3 is free to be used
1017
#else
1018
        movel   d7,a4
1019
        movel   a0,d7
1020
        movel   a4,a0
1021
        movel   d6,a4
1022
        movel   a3,d6
1023
        movel   a4,a3
1024
#endif
1025
        movel   d7,d6           |
1026
        movew   IMM (0),d7      | get a's sign in d7 '
1027
        swap    d6              |
1028
        movew   IMM (0),d6      | and b's sign in d6 '
1029
        eorl    d7,d6           | compare the signs
1030
        bmi     Lsubdf$0        | if the signs are different we have
1031
                                | to subtract
1032
#ifndef __mcoldfire__
1033
        exg     d7,a0           | else we add the numbers
1034
        exg     d6,a3           |
1035
#else
1036
        movel   d7,a4
1037
        movel   a0,d7
1038
        movel   a4,a0
1039
        movel   d6,a4
1040
        movel   a3,d6
1041
        movel   a4,a3
1042
#endif
1043
        addl    d7,d3           |
1044
        addxl   d6,d2           |
1045
        addxl   d5,d1           |
1046
        addxl   d4,d0           |
1047
 
1048
        movel   a2,d4           | return exponent to d4
1049
        movel   a0,d7           |
1050
        andl    IMM (0x80000000),d7 | d7 now has the sign
1051
 
1052
#ifndef __mcoldfire__
1053
        moveml  sp@+,a2-a3
1054
#else
1055
        movel   sp@+,a4
1056
        movel   sp@+,a3
1057
        movel   sp@+,a2
1058
#endif
1059
 
1060
| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
1061
| the case of denormalized numbers in the rounding routine itself).
1062
| As in the addition (not in the subtraction!) we could have set
1063
| one more bit we check this:
1064
        btst    IMM (DBL_MANT_DIG+1),d0
1065
        beq     1f
1066
#ifndef __mcoldfire__
1067
        lsrl    IMM (1),d0
1068
        roxrl   IMM (1),d1
1069
        roxrl   IMM (1),d2
1070
        roxrl   IMM (1),d3
1071
        addw    IMM (1),d4
1072
#else
1073
        lsrl    IMM (1),d3
1074
        btst    IMM (0),d2
1075
        beq     10f
1076
        bset    IMM (31),d3
1077
10:     lsrl    IMM (1),d2
1078
        btst    IMM (0),d1
1079
        beq     11f
1080
        bset    IMM (31),d2
1081
11:     lsrl    IMM (1),d1
1082
        btst    IMM (0),d0
1083
        beq     12f
1084
        bset    IMM (31),d1
1085
12:     lsrl    IMM (1),d0
1086
        addl    IMM (1),d4
1087
#endif
1088
1:
1089
        lea     pc@(Ladddf$5),a0 | to return from rounding routine
1090
        PICLEA  SYM (_fpCCR),a1 | check the rounding mode
1091
#ifdef __mcoldfire__
1092
        clrl    d6
1093
#endif
1094
        movew   a1@(6),d6       | rounding mode in d6
1095
        beq     Lround$to$nearest
1096
#ifndef __mcoldfire__
1097
        cmpw    IMM (ROUND_TO_PLUS),d6
1098
#else
1099
        cmpl    IMM (ROUND_TO_PLUS),d6
1100
#endif
1101
        bhi     Lround$to$minus
1102
        blt     Lround$to$zero
1103
        bra     Lround$to$plus
1104
Ladddf$5:
1105
| Put back the exponent and check for overflow
1106
#ifndef __mcoldfire__
1107
        cmpw    IMM (0x7ff),d4  | is the exponent big?
1108
#else
1109
        cmpl    IMM (0x7ff),d4  | is the exponent big?
1110
#endif
1111
        bge     1f
1112
        bclr    IMM (DBL_MANT_DIG-1),d0
1113
#ifndef __mcoldfire__
1114
        lslw    IMM (4),d4      | put exponent back into position
1115
#else
1116
        lsll    IMM (4),d4      | put exponent back into position
1117
#endif
1118
        swap    d0              |
1119
#ifndef __mcoldfire__
1120
        orw     d4,d0           |
1121
#else
1122
        orl     d4,d0           |
1123
#endif
1124
        swap    d0              |
1125
        bra     Ladddf$ret
1126
1:
1127
        moveq   IMM (ADD),d5
1128
        bra     Ld$overflow
1129
 
1130
Lsubdf$0:
1131
| Here we do the subtraction.
1132
#ifndef __mcoldfire__
1133
        exg     d7,a0           | put sign back in a0
1134
        exg     d6,a3           |
1135
#else
1136
        movel   d7,a4
1137
        movel   a0,d7
1138
        movel   a4,a0
1139
        movel   d6,a4
1140
        movel   a3,d6
1141
        movel   a4,a3
1142
#endif
1143
        subl    d7,d3           |
1144
        subxl   d6,d2           |
1145
        subxl   d5,d1           |
1146
        subxl   d4,d0           |
1147
        beq     Ladddf$ret$1    | if zero just exit
1148
        bpl     1f              | if positive skip the following
1149
        movel   a0,d7           |
1150
        bchg    IMM (31),d7     | change sign bit in d7
1151
        movel   d7,a0           |
1152
        negl    d3              |
1153
        negxl   d2              |
1154
        negxl   d1              | and negate result
1155
        negxl   d0              |
1156
1:
1157
        movel   a2,d4           | return exponent to d4
1158
        movel   a0,d7
1159
        andl    IMM (0x80000000),d7 | isolate sign bit
1160
#ifndef __mcoldfire__
1161
        moveml  sp@+,a2-a3      |
1162
#else
1163
        movel   sp@+,a4
1164
        movel   sp@+,a3
1165
        movel   sp@+,a2
1166
#endif
1167
 
1168
| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
1169
| the case of denormalized numbers in the rounding routine itself).
1170
| As in the addition (not in the subtraction!) we could have set
1171
| one more bit we check this:
1172
        btst    IMM (DBL_MANT_DIG+1),d0
1173
        beq     1f
1174
#ifndef __mcoldfire__
1175
        lsrl    IMM (1),d0
1176
        roxrl   IMM (1),d1
1177
        roxrl   IMM (1),d2
1178
        roxrl   IMM (1),d3
1179
        addw    IMM (1),d4
1180
#else
1181
        lsrl    IMM (1),d3
1182
        btst    IMM (0),d2
1183
        beq     10f
1184
        bset    IMM (31),d3
1185
10:     lsrl    IMM (1),d2
1186
        btst    IMM (0),d1
1187
        beq     11f
1188
        bset    IMM (31),d2
1189
11:     lsrl    IMM (1),d1
1190
        btst    IMM (0),d0
1191
        beq     12f
1192
        bset    IMM (31),d1
1193
12:     lsrl    IMM (1),d0
1194
        addl    IMM (1),d4
1195
#endif
1196
1:
1197
        lea     pc@(Lsubdf$1),a0 | to return from rounding routine
1198
        PICLEA  SYM (_fpCCR),a1 | check the rounding mode
1199
#ifdef __mcoldfire__
1200
        clrl    d6
1201
#endif
1202
        movew   a1@(6),d6       | rounding mode in d6
1203
        beq     Lround$to$nearest
1204
#ifndef __mcoldfire__
1205
        cmpw    IMM (ROUND_TO_PLUS),d6
1206
#else
1207
        cmpl    IMM (ROUND_TO_PLUS),d6
1208
#endif
1209
        bhi     Lround$to$minus
1210
        blt     Lround$to$zero
1211
        bra     Lround$to$plus
1212
Lsubdf$1:
1213
| Put back the exponent and sign (we don't have overflow). '
1214
        bclr    IMM (DBL_MANT_DIG-1),d0
1215
#ifndef __mcoldfire__
1216
        lslw    IMM (4),d4      | put exponent back into position
1217
#else
1218
        lsll    IMM (4),d4      | put exponent back into position
1219
#endif
1220
        swap    d0              |
1221
#ifndef __mcoldfire__
1222
        orw     d4,d0           |
1223
#else
1224
        orl     d4,d0           |
1225
#endif
1226
        swap    d0              |
1227
        bra     Ladddf$ret
1228
 
1229
| If one of the numbers was too small (difference of exponents >=
1230
| DBL_MANT_DIG+1) we return the other (and now we don't have to '
1231
| check for finiteness or zero).
1232
Ladddf$a$small:
1233
#ifndef __mcoldfire__
1234
        moveml  sp@+,a2-a3
1235
#else
1236
        movel   sp@+,a4
1237
        movel   sp@+,a3
1238
        movel   sp@+,a2
1239
#endif
1240
        movel   a6@(16),d0
1241
        movel   a6@(20),d1
1242
        PICLEA  SYM (_fpCCR),a0
1243
        movew   IMM (0),a0@
1244
#ifndef __mcoldfire__
1245
        moveml  sp@+,d2-d7      | restore data registers
1246
#else
1247
        moveml  sp@,d2-d7
1248
        | XXX if frame pointer is ever removed, stack pointer must
1249
        | be adjusted here.
1250
#endif
1251
        unlk    a6              | and return
1252
        rts
1253
 
1254
Ladddf$b$small:
1255
#ifndef __mcoldfire__
1256
        moveml  sp@+,a2-a3
1257
#else
1258
        movel   sp@+,a4
1259
        movel   sp@+,a3
1260
        movel   sp@+,a2
1261
#endif
1262
        movel   a6@(8),d0
1263
        movel   a6@(12),d1
1264
        PICLEA  SYM (_fpCCR),a0
1265
        movew   IMM (0),a0@
1266
#ifndef __mcoldfire__
1267
        moveml  sp@+,d2-d7      | restore data registers
1268
#else
1269
        moveml  sp@,d2-d7
1270
        | XXX if frame pointer is ever removed, stack pointer must
1271
        | be adjusted here.
1272
#endif
1273
        unlk    a6              | and return
1274
        rts
1275
 
1276
Ladddf$a$den:
1277
        movel   d7,d4           | d7 contains 0x00200000
1278
        bra     Ladddf$1
1279
 
1280
Ladddf$b$den:
1281
        movel   d7,d5           | d7 contains 0x00200000
1282
        notl    d6
1283
        bra     Ladddf$2
1284
 
1285
Ladddf$b:
1286
| Return b (if a is zero)
1287
        movel   d2,d0
1288
        movel   d3,d1
1289
        bne     1f                      | Check if b is -0
1290
        cmpl    IMM (0x80000000),d0
1291
        bne     1f
1292
        andl    IMM (0x80000000),d7     | Use the sign of a
1293
        clrl    d0
1294
        bra     Ladddf$ret
1295
Ladddf$a:
1296
        movel   a6@(8),d0
1297
        movel   a6@(12),d1
1298
1:
1299
        moveq   IMM (ADD),d5
1300
| Check for NaN and +/-INFINITY.
1301
        movel   d0,d7                   |
1302
        andl    IMM (0x80000000),d7     |
1303
        bclr    IMM (31),d0             |
1304
        cmpl    IMM (0x7ff00000),d0     |
1305
        bge     2f                      |
1306
        movel   d0,d0                   | check for zero, since we don't  '
1307
        bne     Ladddf$ret              | want to return -0 by mistake
1308
        bclr    IMM (31),d7             |
1309
        bra     Ladddf$ret              |
1310
2:
1311
        andl    IMM (0x000fffff),d0     | check for NaN (nonzero fraction)
1312
        orl     d1,d0                   |
1313
        bne     Ld$inop                 |
1314
        bra     Ld$infty                |
1315
 
1316
Ladddf$ret$1:
1317
#ifndef __mcoldfire__
1318
        moveml  sp@+,a2-a3      | restore regs and exit
1319
#else
1320
        movel   sp@+,a4
1321
        movel   sp@+,a3
1322
        movel   sp@+,a2
1323
#endif
1324
 
1325
Ladddf$ret:
1326
| Normal exit.
1327
        PICLEA  SYM (_fpCCR),a0
1328
        movew   IMM (0),a0@
1329
        orl     d7,d0           | put sign bit back
1330
#ifndef __mcoldfire__
1331
        moveml  sp@+,d2-d7
1332
#else
1333
        moveml  sp@,d2-d7
1334
        | XXX if frame pointer is ever removed, stack pointer must
1335
        | be adjusted here.
1336
#endif
1337
        unlk    a6
1338
        rts
1339
 
1340
Ladddf$ret$den:
1341
| Return a denormalized number.
1342
#ifndef __mcoldfire__
1343
        lsrl    IMM (1),d0      | shift right once more
1344
        roxrl   IMM (1),d1      |
1345
#else
1346
        lsrl    IMM (1),d1
1347
        btst    IMM (0),d0
1348
        beq     10f
1349
        bset    IMM (31),d1
1350
10:     lsrl    IMM (1),d0
1351
#endif
1352
        bra     Ladddf$ret
1353
 
1354
Ladddf$nf:
1355
        moveq   IMM (ADD),d5
1356
| This could be faster but it is not worth the effort, since it is not
1357
| executed very often. We sacrifice speed for clarity here.
1358
        movel   a6@(8),d0       | get the numbers back (remember that we
1359
        movel   a6@(12),d1      | did some processing already)
1360
        movel   a6@(16),d2      |
1361
        movel   a6@(20),d3      |
1362
        movel   IMM (0x7ff00000),d4 | useful constant (INFINITY)
1363
        movel   d0,d7           | save sign bits
1364
        movel   d2,d6           |
1365
        bclr    IMM (31),d0     | clear sign bits
1366
        bclr    IMM (31),d2     |
1367
| We know that one of them is either NaN of +/-INFINITY
1368
| Check for NaN (if either one is NaN return NaN)
1369
        cmpl    d4,d0           | check first a (d0)
1370
        bhi     Ld$inop         | if d0 > 0x7ff00000 or equal and
1371
        bne     2f
1372
        tstl    d1              | d1 > 0, a is NaN
1373
        bne     Ld$inop         |
1374
2:      cmpl    d4,d2           | check now b (d1)
1375
        bhi     Ld$inop         |
1376
        bne     3f
1377
        tstl    d3              |
1378
        bne     Ld$inop         |
1379
3:
1380
| Now comes the check for +/-INFINITY. We know that both are (maybe not
1381
| finite) numbers, but we have to check if both are infinite whether we
1382
| are adding or subtracting them.
1383
        eorl    d7,d6           | to check sign bits
1384
        bmi     1f
1385
        andl    IMM (0x80000000),d7 | get (common) sign bit
1386
        bra     Ld$infty
1387
1:
1388
| We know one (or both) are infinite, so we test for equality between the
1389
| two numbers (if they are equal they have to be infinite both, so we
1390
| return NaN).
1391
        cmpl    d2,d0           | are both infinite?
1392
        bne     1f              | if d0 <> d2 they are not equal
1393
        cmpl    d3,d1           | if d0 == d2 test d3 and d1
1394
        beq     Ld$inop         | if equal return NaN
1395
1:
1396
        andl    IMM (0x80000000),d7 | get a's sign bit '
1397
        cmpl    d4,d0           | test now for infinity
1398
        beq     Ld$infty        | if a is INFINITY return with this sign
1399
        bchg    IMM (31),d7     | else we know b is INFINITY and has
1400
        bra     Ld$infty        | the opposite sign
1401
 
1402
|=============================================================================
1403
|                              __muldf3
1404
|=============================================================================
1405
 
1406
| double __muldf3(double, double);
1407
SYM (__muldf3):
1408
#ifndef __mcoldfire__
1409
        link    a6,IMM (0)
1410
        moveml  d2-d7,sp@-
1411
#else
1412
        link    a6,IMM (-24)
1413
        moveml  d2-d7,sp@
1414
#endif
1415
        movel   a6@(8),d0               | get a into d0-d1
1416
        movel   a6@(12),d1              |
1417
        movel   a6@(16),d2              | and b into d2-d3
1418
        movel   a6@(20),d3              |
1419
        movel   d0,d7                   | d7 will hold the sign of the product
1420
        eorl    d2,d7                   |
1421
        andl    IMM (0x80000000),d7     |
1422
        movel   d7,a0                   | save sign bit into a0
1423
        movel   IMM (0x7ff00000),d7     | useful constant (+INFINITY)
1424
        movel   d7,d6                   | another (mask for fraction)
1425
        notl    d6                      |
1426
        bclr    IMM (31),d0             | get rid of a's sign bit '
1427
        movel   d0,d4                   |
1428
        orl     d1,d4                   |
1429
        beq     Lmuldf$a$0              | branch if a is zero
1430
        movel   d0,d4                   |
1431
        bclr    IMM (31),d2             | get rid of b's sign bit '
1432
        movel   d2,d5                   |
1433
        orl     d3,d5                   |
1434
        beq     Lmuldf$b$0              | branch if b is zero
1435
        movel   d2,d5                   |
1436
        cmpl    d7,d0                   | is a big?
1437
        bhi     Lmuldf$inop             | if a is NaN return NaN
1438
        beq     Lmuldf$a$nf             | we still have to check d1 and b ...
1439
        cmpl    d7,d2                   | now compare b with INFINITY
1440
        bhi     Lmuldf$inop             | is b NaN?
1441
        beq     Lmuldf$b$nf             | we still have to check d3 ...
1442
| Here we have both numbers finite and nonzero (and with no sign bit).
1443
| Now we get the exponents into d4 and d5.
1444
        andl    d7,d4                   | isolate exponent in d4
1445
        beq     Lmuldf$a$den            | if exponent zero, have denormalized
1446
        andl    d6,d0                   | isolate fraction
1447
        orl     IMM (0x00100000),d0     | and put hidden bit back
1448
        swap    d4                      | I like exponents in the first byte
1449
#ifndef __mcoldfire__
1450
        lsrw    IMM (4),d4              |
1451
#else
1452
        lsrl    IMM (4),d4              |
1453
#endif
1454
Lmuldf$1:
1455
        andl    d7,d5                   |
1456
        beq     Lmuldf$b$den            |
1457
        andl    d6,d2                   |
1458
        orl     IMM (0x00100000),d2     | and put hidden bit back
1459
        swap    d5                      |
1460
#ifndef __mcoldfire__
1461
        lsrw    IMM (4),d5              |
1462
#else
1463
        lsrl    IMM (4),d5              |
1464
#endif
1465
Lmuldf$2:                               |
1466
#ifndef __mcoldfire__
1467
        addw    d5,d4                   | add exponents
1468
        subw    IMM (D_BIAS+1),d4       | and subtract bias (plus one)
1469
#else
1470
        addl    d5,d4                   | add exponents
1471
        subl    IMM (D_BIAS+1),d4       | and subtract bias (plus one)
1472
#endif
1473
 
1474
| We are now ready to do the multiplication. The situation is as follows:
1475
| both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were
1476
| denormalized to start with!), which means that in the product bit 104
1477
| (which will correspond to bit 8 of the fourth long) is set.
1478
 
1479
| Here we have to do the product.
1480
| To do it we have to juggle the registers back and forth, as there are not
1481
| enough to keep everything in them. So we use the address registers to keep
1482
| some intermediate data.
1483
 
1484
#ifndef __mcoldfire__
1485
        moveml  a2-a3,sp@-      | save a2 and a3 for temporary use
1486
#else
1487
        movel   a2,sp@-
1488
        movel   a3,sp@-
1489
        movel   a4,sp@-
1490
#endif
1491
        movel   IMM (0),a2      | a2 is a null register
1492
        movel   d4,a3           | and a3 will preserve the exponent
1493
 
1494
| First, shift d2-d3 so bit 20 becomes bit 31:
1495
#ifndef __mcoldfire__
1496
        rorl    IMM (5),d2      | rotate d2 5 places right
1497
        swap    d2              | and swap it
1498
        rorl    IMM (5),d3      | do the same thing with d3
1499
        swap    d3              |
1500
        movew   d3,d6           | get the rightmost 11 bits of d3
1501
        andw    IMM (0x07ff),d6 |
1502
        orw     d6,d2           | and put them into d2
1503
        andw    IMM (0xf800),d3 | clear those bits in d3
1504
#else
1505
        moveq   IMM (11),d7     | left shift d2 11 bits
1506
        lsll    d7,d2
1507
        movel   d3,d6           | get a copy of d3
1508
        lsll    d7,d3           | left shift d3 11 bits
1509
        andl    IMM (0xffe00000),d6 | get the top 11 bits of d3
1510
        moveq   IMM (21),d7     | right shift them 21 bits
1511
        lsrl    d7,d6
1512
        orl     d6,d2           | stick them at the end of d2
1513
#endif
1514
 
1515
        movel   d2,d6           | move b into d6-d7
1516
        movel   d3,d7           | move a into d4-d5
1517
        movel   d0,d4           | and clear d0-d1-d2-d3 (to put result)
1518
        movel   d1,d5           |
1519
        movel   IMM (0),d3      |
1520
        movel   d3,d2           |
1521
        movel   d3,d1           |
1522
        movel   d3,d0           |
1523
 
1524
| We use a1 as counter:
1525
        movel   IMM (DBL_MANT_DIG-1),a1
1526
#ifndef __mcoldfire__
1527
        exg     d7,a1
1528
#else
1529
        movel   d7,a4
1530
        movel   a1,d7
1531
        movel   a4,a1
1532
#endif
1533
 
1534
1:
1535
#ifndef __mcoldfire__
1536
        exg     d7,a1           | put counter back in a1
1537
#else
1538
        movel   d7,a4
1539
        movel   a1,d7
1540
        movel   a4,a1
1541
#endif
1542
        addl    d3,d3           | shift sum once left
1543
        addxl   d2,d2           |
1544
        addxl   d1,d1           |
1545
        addxl   d0,d0           |
1546
        addl    d7,d7           |
1547
        addxl   d6,d6           |
1548
        bcc     2f              | if bit clear skip the following
1549
#ifndef __mcoldfire__
1550
        exg     d7,a2           |
1551
#else
1552
        movel   d7,a4
1553
        movel   a2,d7
1554
        movel   a4,a2
1555
#endif
1556
        addl    d5,d3           | else add a to the sum
1557
        addxl   d4,d2           |
1558
        addxl   d7,d1           |
1559
        addxl   d7,d0           |
1560
#ifndef __mcoldfire__
1561
        exg     d7,a2           |
1562
#else
1563
        movel   d7,a4
1564
        movel   a2,d7
1565
        movel   a4,a2
1566
#endif
1567
2:
1568
#ifndef __mcoldfire__
1569
        exg     d7,a1           | put counter in d7
1570
        dbf     d7,1b           | decrement and branch
1571
#else
1572
        movel   d7,a4
1573
        movel   a1,d7
1574
        movel   a4,a1
1575
        subql   IMM (1),d7
1576
        bpl     1b
1577
#endif
1578
 
1579
        movel   a3,d4           | restore exponent
1580
#ifndef __mcoldfire__
1581
        moveml  sp@+,a2-a3
1582
#else
1583
        movel   sp@+,a4
1584
        movel   sp@+,a3
1585
        movel   sp@+,a2
1586
#endif
1587
 
1588
| Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The
1589
| first thing to do now is to normalize it so bit 8 becomes bit
1590
| DBL_MANT_DIG-32 (to do the rounding); later we will shift right.
1591
        swap    d0
1592
        swap    d1
1593
        movew   d1,d0
1594
        swap    d2
1595
        movew   d2,d1
1596
        swap    d3
1597
        movew   d3,d2
1598
        movew   IMM (0),d3
1599
#ifndef __mcoldfire__
1600
        lsrl    IMM (1),d0
1601
        roxrl   IMM (1),d1
1602
        roxrl   IMM (1),d2
1603
        roxrl   IMM (1),d3
1604
        lsrl    IMM (1),d0
1605
        roxrl   IMM (1),d1
1606
        roxrl   IMM (1),d2
1607
        roxrl   IMM (1),d3
1608
        lsrl    IMM (1),d0
1609
        roxrl   IMM (1),d1
1610
        roxrl   IMM (1),d2
1611
        roxrl   IMM (1),d3
1612
#else
1613
        moveq   IMM (29),d6
1614
        lsrl    IMM (3),d3
1615
        movel   d2,d7
1616
        lsll    d6,d7
1617
        orl     d7,d3
1618
        lsrl    IMM (3),d2
1619
        movel   d1,d7
1620
        lsll    d6,d7
1621
        orl     d7,d2
1622
        lsrl    IMM (3),d1
1623
        movel   d0,d7
1624
        lsll    d6,d7
1625
        orl     d7,d1
1626
        lsrl    IMM (3),d0
1627
#endif
1628
 
1629
| Now round, check for over- and underflow, and exit.
1630
        movel   a0,d7           | get sign bit back into d7
1631
        moveq   IMM (MULTIPLY),d5
1632
 
1633
        btst    IMM (DBL_MANT_DIG+1-32),d0
1634
        beq     Lround$exit
1635
#ifndef __mcoldfire__
1636
        lsrl    IMM (1),d0
1637
        roxrl   IMM (1),d1
1638
        addw    IMM (1),d4
1639
#else
1640
        lsrl    IMM (1),d1
1641
        btst    IMM (0),d0
1642
        beq     10f
1643
        bset    IMM (31),d1
1644
10:     lsrl    IMM (1),d0
1645
        addl    IMM (1),d4
1646
#endif
1647
        bra     Lround$exit
1648
 
1649
Lmuldf$inop:
1650
        moveq   IMM (MULTIPLY),d5
1651
        bra     Ld$inop
1652
 
1653
Lmuldf$b$nf:
1654
        moveq   IMM (MULTIPLY),d5
1655
        movel   a0,d7           | get sign bit back into d7
1656
        tstl    d3              | we know d2 == 0x7ff00000, so check d3
1657
        bne     Ld$inop         | if d3 <> 0 b is NaN
1658
        bra     Ld$overflow     | else we have overflow (since a is finite)
1659
 
1660
Lmuldf$a$nf:
1661
        moveq   IMM (MULTIPLY),d5
1662
        movel   a0,d7           | get sign bit back into d7
1663
        tstl    d1              | we know d0 == 0x7ff00000, so check d1
1664
        bne     Ld$inop         | if d1 <> 0 a is NaN
1665
        bra     Ld$overflow     | else signal overflow
1666
 
1667
| If either number is zero return zero, unless the other is +/-INFINITY or
1668
| NaN, in which case we return NaN.
1669
Lmuldf$b$0:
1670
        moveq   IMM (MULTIPLY),d5
1671
#ifndef __mcoldfire__
1672
        exg     d2,d0           | put b (==0) into d0-d1
1673
        exg     d3,d1           | and a (with sign bit cleared) into d2-d3
1674
        movel   a0,d0           | set result sign
1675
#else
1676
        movel   d0,d2           | put a into d2-d3
1677
        movel   d1,d3
1678
        movel   a0,d0           | put result zero into d0-d1
1679
        movq    IMM(0),d1
1680
#endif
1681
        bra     1f
1682
Lmuldf$a$0:
1683
        movel   a0,d0           | set result sign
1684
        movel   a6@(16),d2      | put b into d2-d3 again
1685
        movel   a6@(20),d3      |
1686
        bclr    IMM (31),d2     | clear sign bit
1687
1:      cmpl    IMM (0x7ff00000),d2 | check for non-finiteness
1688
        bge     Ld$inop         | in case NaN or +/-INFINITY return NaN
1689
        PICLEA  SYM (_fpCCR),a0
1690
        movew   IMM (0),a0@
1691
#ifndef __mcoldfire__
1692
        moveml  sp@+,d2-d7
1693
#else
1694
        moveml  sp@,d2-d7
1695
        | XXX if frame pointer is ever removed, stack pointer must
1696
        | be adjusted here.
1697
#endif
1698
        unlk    a6
1699
        rts
1700
 
1701
| If a number is denormalized we put an exponent of 1 but do not put the
1702
| hidden bit back into the fraction; instead we shift left until bit 21
1703
| (the hidden bit) is set, adjusting the exponent accordingly. We do this
1704
| to ensure that the product of the fractions is close to 1.
1705
Lmuldf$a$den:
1706
        movel   IMM (1),d4
1707
        andl    d6,d0
1708
1:      addl    d1,d1           | shift a left until bit 20 is set
1709
        addxl   d0,d0           |
1710
#ifndef __mcoldfire__
1711
        subw    IMM (1),d4      | and adjust exponent
1712
#else
1713
        subl    IMM (1),d4      | and adjust exponent
1714
#endif
1715
        btst    IMM (20),d0     |
1716
        bne     Lmuldf$1        |
1717
        bra     1b
1718
 
1719
Lmuldf$b$den:
1720
        movel   IMM (1),d5
1721
        andl    d6,d2
1722
1:      addl    d3,d3           | shift b left until bit 20 is set
1723
        addxl   d2,d2           |
1724
#ifndef __mcoldfire__
1725
        subw    IMM (1),d5      | and adjust exponent
1726
#else
1727
        subql   IMM (1),d5      | and adjust exponent
1728
#endif
1729
        btst    IMM (20),d2     |
1730
        bne     Lmuldf$2        |
1731
        bra     1b
1732
 
1733
 
1734
|=============================================================================
1735
|                              __divdf3
1736
|=============================================================================
1737
 
1738
| double __divdf3(double, double);
1739
SYM (__divdf3):
1740
#ifndef __mcoldfire__
1741
        link    a6,IMM (0)
1742
        moveml  d2-d7,sp@-
1743
#else
1744
        link    a6,IMM (-24)
1745
        moveml  d2-d7,sp@
1746
#endif
1747
        movel   a6@(8),d0       | get a into d0-d1
1748
        movel   a6@(12),d1      |
1749
        movel   a6@(16),d2      | and b into d2-d3
1750
        movel   a6@(20),d3      |
1751
        movel   d0,d7           | d7 will hold the sign of the result
1752
        eorl    d2,d7           |
1753
        andl    IMM (0x80000000),d7
1754
        movel   d7,a0           | save sign into a0
1755
        movel   IMM (0x7ff00000),d7 | useful constant (+INFINITY)
1756
        movel   d7,d6           | another (mask for fraction)
1757
        notl    d6              |
1758
        bclr    IMM (31),d0     | get rid of a's sign bit '
1759
        movel   d0,d4           |
1760
        orl     d1,d4           |
1761
        beq     Ldivdf$a$0      | branch if a is zero
1762
        movel   d0,d4           |
1763
        bclr    IMM (31),d2     | get rid of b's sign bit '
1764
        movel   d2,d5           |
1765
        orl     d3,d5           |
1766
        beq     Ldivdf$b$0      | branch if b is zero
1767
        movel   d2,d5
1768
        cmpl    d7,d0           | is a big?
1769
        bhi     Ldivdf$inop     | if a is NaN return NaN
1770
        beq     Ldivdf$a$nf     | if d0 == 0x7ff00000 we check d1
1771
        cmpl    d7,d2           | now compare b with INFINITY
1772
        bhi     Ldivdf$inop     | if b is NaN return NaN
1773
        beq     Ldivdf$b$nf     | if d2 == 0x7ff00000 we check d3
1774
| Here we have both numbers finite and nonzero (and with no sign bit).
1775
| Now we get the exponents into d4 and d5 and normalize the numbers to
1776
| ensure that the ratio of the fractions is around 1. We do this by
1777
| making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit)
1778
| set, even if they were denormalized to start with.
1779
| Thus, the result will satisfy: 2 > result > 1/2.
1780
        andl    d7,d4           | and isolate exponent in d4
1781
        beq     Ldivdf$a$den    | if exponent is zero we have a denormalized
1782
        andl    d6,d0           | and isolate fraction
1783
        orl     IMM (0x00100000),d0 | and put hidden bit back
1784
        swap    d4              | I like exponents in the first byte
1785
#ifndef __mcoldfire__
1786
        lsrw    IMM (4),d4      |
1787
#else
1788
        lsrl    IMM (4),d4      |
1789
#endif
1790
Ldivdf$1:                       |
1791
        andl    d7,d5           |
1792
        beq     Ldivdf$b$den    |
1793
        andl    d6,d2           |
1794
        orl     IMM (0x00100000),d2
1795
        swap    d5              |
1796
#ifndef __mcoldfire__
1797
        lsrw    IMM (4),d5      |
1798
#else
1799
        lsrl    IMM (4),d5      |
1800
#endif
1801
Ldivdf$2:                       |
1802
#ifndef __mcoldfire__
1803
        subw    d5,d4           | subtract exponents
1804
        addw    IMM (D_BIAS),d4 | and add bias
1805
#else
1806
        subl    d5,d4           | subtract exponents
1807
        addl    IMM (D_BIAS),d4 | and add bias
1808
#endif
1809
 
1810
| We are now ready to do the division. We have prepared things in such a way
1811
| that the ratio of the fractions will be less than 2 but greater than 1/2.
1812
| At this point the registers in use are:
1813
| d0-d1 hold a (first operand, bit DBL_MANT_DIG-32=0, bit
1814
| DBL_MANT_DIG-1-32=1)
1815
| d2-d3 hold b (second operand, bit DBL_MANT_DIG-32=1)
1816
| d4    holds the difference of the exponents, corrected by the bias
1817
| a0    holds the sign of the ratio
1818
 
1819
| To do the rounding correctly we need to keep information about the
1820
| nonsignificant bits. One way to do this would be to do the division
1821
| using four registers; another is to use two registers (as originally
1822
| I did), but use a sticky bit to preserve information about the
1823
| fractional part. Note that we can keep that info in a1, which is not
1824
| used.
1825
        movel   IMM (0),d6      | d6-d7 will hold the result
1826
        movel   d6,d7           |
1827
        movel   IMM (0),a1      | and a1 will hold the sticky bit
1828
 
1829
        movel   IMM (DBL_MANT_DIG-32+1),d5
1830
 
1831
1:      cmpl    d0,d2           | is a < b?
1832
        bhi     3f              | if b > a skip the following
1833
        beq     4f              | if d0==d2 check d1 and d3
1834
2:      subl    d3,d1           |
1835
        subxl   d2,d0           | a <-- a - b
1836
        bset    d5,d6           | set the corresponding bit in d6
1837
3:      addl    d1,d1           | shift a by 1
1838
        addxl   d0,d0           |
1839
#ifndef __mcoldfire__
1840
        dbra    d5,1b           | and branch back
1841
#else
1842
        subql   IMM (1), d5
1843
        bpl     1b
1844
#endif
1845
        bra     5f
1846
4:      cmpl    d1,d3           | here d0==d2, so check d1 and d3
1847
        bhi     3b              | if d1 > d2 skip the subtraction
1848
        bra     2b              | else go do it
1849
5:
1850
| Here we have to start setting the bits in the second long.
1851
        movel   IMM (31),d5     | again d5 is counter
1852
 
1853
1:      cmpl    d0,d2           | is a < b?
1854
        bhi     3f              | if b > a skip the following
1855
        beq     4f              | if d0==d2 check d1 and d3
1856
2:      subl    d3,d1           |
1857
        subxl   d2,d0           | a <-- a - b
1858
        bset    d5,d7           | set the corresponding bit in d7
1859
3:      addl    d1,d1           | shift a by 1
1860
        addxl   d0,d0           |
1861
#ifndef __mcoldfire__
1862
        dbra    d5,1b           | and branch back
1863
#else
1864
        subql   IMM (1), d5
1865
        bpl     1b
1866
#endif
1867
        bra     5f
1868
4:      cmpl    d1,d3           | here d0==d2, so check d1 and d3
1869
        bhi     3b              | if d1 > d2 skip the subtraction
1870
        bra     2b              | else go do it
1871
5:
1872
| Now go ahead checking until we hit a one, which we store in d2.
1873
        movel   IMM (DBL_MANT_DIG),d5
1874
1:      cmpl    d2,d0           | is a < b?
1875
        bhi     4f              | if b < a, exit
1876
        beq     3f              | if d0==d2 check d1 and d3
1877
2:      addl    d1,d1           | shift a by 1
1878
        addxl   d0,d0           |
1879
#ifndef __mcoldfire__
1880
        dbra    d5,1b           | and branch back
1881
#else
1882
        subql   IMM (1), d5
1883
        bpl     1b
1884
#endif
1885
        movel   IMM (0),d2      | here no sticky bit was found
1886
        movel   d2,d3
1887
        bra     5f
1888
3:      cmpl    d1,d3           | here d0==d2, so check d1 and d3
1889
        bhi     2b              | if d1 > d2 go back
1890
4:
1891
| Here put the sticky bit in d2-d3 (in the position which actually corresponds
1892
| to it; if you don't do this the algorithm loses in some cases). '
1893
        movel   IMM (0),d2
1894
        movel   d2,d3
1895
#ifndef __mcoldfire__
1896
        subw    IMM (DBL_MANT_DIG),d5
1897
        addw    IMM (63),d5
1898
        cmpw    IMM (31),d5
1899
#else
1900
        subl    IMM (DBL_MANT_DIG),d5
1901
        addl    IMM (63),d5
1902
        cmpl    IMM (31),d5
1903
#endif
1904
        bhi     2f
1905
1:      bset    d5,d3
1906
        bra     5f
1907
#ifndef __mcoldfire__
1908
        subw    IMM (32),d5
1909
#else
1910
        subl    IMM (32),d5
1911
#endif
1912
2:      bset    d5,d2
1913
5:
1914
| Finally we are finished! Move the longs in the address registers to
1915
| their final destination:
1916
        movel   d6,d0
1917
        movel   d7,d1
1918
        movel   IMM (0),d3
1919
 
1920
| Here we have finished the division, with the result in d0-d1-d2-d3, with
1921
| 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set.
1922
| If it is not, then definitely bit 21 is set. Normalize so bit 22 is
1923
| not set:
1924
        btst    IMM (DBL_MANT_DIG-32+1),d0
1925
        beq     1f
1926
#ifndef __mcoldfire__
1927
        lsrl    IMM (1),d0
1928
        roxrl   IMM (1),d1
1929
        roxrl   IMM (1),d2
1930
        roxrl   IMM (1),d3
1931
        addw    IMM (1),d4
1932
#else
1933
        lsrl    IMM (1),d3
1934
        btst    IMM (0),d2
1935
        beq     10f
1936
        bset    IMM (31),d3
1937
10:     lsrl    IMM (1),d2
1938
        btst    IMM (0),d1
1939
        beq     11f
1940
        bset    IMM (31),d2
1941
11:     lsrl    IMM (1),d1
1942
        btst    IMM (0),d0
1943
        beq     12f
1944
        bset    IMM (31),d1
1945
12:     lsrl    IMM (1),d0
1946
        addl    IMM (1),d4
1947
#endif
1948
1:
1949
| Now round, check for over- and underflow, and exit.
1950
        movel   a0,d7           | restore sign bit to d7
1951
        moveq   IMM (DIVIDE),d5
1952
        bra     Lround$exit
1953
 
1954
Ldivdf$inop:
1955
        moveq   IMM (DIVIDE),d5
1956
        bra     Ld$inop
1957
 
1958
Ldivdf$a$0:
1959
| If a is zero check to see whether b is zero also. In that case return
1960
| NaN; then check if b is NaN, and return NaN also in that case. Else
1961
| return a properly signed zero.
1962
        moveq   IMM (DIVIDE),d5
1963
        bclr    IMM (31),d2     |
1964
        movel   d2,d4           |
1965
        orl     d3,d4           |
1966
        beq     Ld$inop         | if b is also zero return NaN
1967
        cmpl    IMM (0x7ff00000),d2 | check for NaN
1968
        bhi     Ld$inop         |
1969
        blt     1f              |
1970
        tstl    d3              |
1971
        bne     Ld$inop         |
1972
1:      movel   a0,d0           | else return signed zero
1973
        moveq   IMM(0),d1       |
1974
        PICLEA  SYM (_fpCCR),a0 | clear exception flags
1975
        movew   IMM (0),a0@     |
1976
#ifndef __mcoldfire__
1977
        moveml  sp@+,d2-d7      |
1978
#else
1979
        moveml  sp@,d2-d7       |
1980
        | XXX if frame pointer is ever removed, stack pointer must
1981
        | be adjusted here.
1982
#endif
1983
        unlk    a6              |
1984
        rts                     |
1985
 
1986
Ldivdf$b$0:
1987
        moveq   IMM (DIVIDE),d5
1988
| If we got here a is not zero. Check if a is NaN; in that case return NaN,
1989
| else return +/-INFINITY. Remember that a is in d0 with the sign bit
1990
| cleared already.
1991
        movel   a0,d7           | put a's sign bit back in d7 '
1992
        cmpl    IMM (0x7ff00000),d0 | compare d0 with INFINITY
1993
        bhi     Ld$inop         | if larger it is NaN
1994
        tstl    d1              |
1995
        bne     Ld$inop         |
1996
        bra     Ld$div$0        | else signal DIVIDE_BY_ZERO
1997
 
1998
Ldivdf$b$nf:
1999
        moveq   IMM (DIVIDE),d5
2000
| If d2 == 0x7ff00000 we have to check d3.
2001
        tstl    d3              |
2002
        bne     Ld$inop         | if d3 <> 0, b is NaN
2003
        bra     Ld$underflow    | else b is +/-INFINITY, so signal underflow
2004
 
2005
Ldivdf$a$nf:
2006
        moveq   IMM (DIVIDE),d5
2007
| If d0 == 0x7ff00000 we have to check d1.
2008
        tstl    d1              |
2009
        bne     Ld$inop         | if d1 <> 0, a is NaN
2010
| If a is INFINITY we have to check b
2011
        cmpl    d7,d2           | compare b with INFINITY
2012
        bge     Ld$inop         | if b is NaN or INFINITY return NaN
2013
        tstl    d3              |
2014
        bne     Ld$inop         |
2015
        bra     Ld$overflow     | else return overflow
2016
 
2017
| If a number is denormalized we put an exponent of 1 but do not put the
2018
| bit back into the fraction.
2019
Ldivdf$a$den:
2020
        movel   IMM (1),d4
2021
        andl    d6,d0
2022
1:      addl    d1,d1           | shift a left until bit 20 is set
2023
        addxl   d0,d0
2024
#ifndef __mcoldfire__
2025
        subw    IMM (1),d4      | and adjust exponent
2026
#else
2027
        subl    IMM (1),d4      | and adjust exponent
2028
#endif
2029
        btst    IMM (DBL_MANT_DIG-32-1),d0
2030
        bne     Ldivdf$1
2031
        bra     1b
2032
 
2033
Ldivdf$b$den:
2034
        movel   IMM (1),d5
2035
        andl    d6,d2
2036
1:      addl    d3,d3           | shift b left until bit 20 is set
2037
        addxl   d2,d2
2038
#ifndef __mcoldfire__
2039
        subw    IMM (1),d5      | and adjust exponent
2040
#else
2041
        subql   IMM (1),d5      | and adjust exponent
2042
#endif
2043
        btst    IMM (DBL_MANT_DIG-32-1),d2
2044
        bne     Ldivdf$2
2045
        bra     1b
2046
 
2047
Lround$exit:
2048
| This is a common exit point for __muldf3 and __divdf3. When they enter
2049
| this point the sign of the result is in d7, the result in d0-d1, normalized
2050
| so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4.
2051
 
2052
| First check for underlow in the exponent:
2053
#ifndef __mcoldfire__
2054
        cmpw    IMM (-DBL_MANT_DIG-1),d4
2055
#else
2056
        cmpl    IMM (-DBL_MANT_DIG-1),d4
2057
#endif
2058
        blt     Ld$underflow
2059
| It could happen that the exponent is less than 1, in which case the
2060
| number is denormalized. In this case we shift right and adjust the
2061
| exponent until it becomes 1 or the fraction is zero (in the latter case
2062
| we signal underflow and return zero).
2063
        movel   d7,a0           |
2064
        movel   IMM (0),d6      | use d6-d7 to collect bits flushed right
2065
        movel   d6,d7           | use d6-d7 to collect bits flushed right
2066
#ifndef __mcoldfire__
2067
        cmpw    IMM (1),d4      | if the exponent is less than 1 we
2068
#else
2069
        cmpl    IMM (1),d4      | if the exponent is less than 1 we
2070
#endif
2071
        bge     2f              | have to shift right (denormalize)
2072
1:
2073
#ifndef __mcoldfire__
2074
        addw    IMM (1),d4      | adjust the exponent
2075
        lsrl    IMM (1),d0      | shift right once
2076
        roxrl   IMM (1),d1      |
2077
        roxrl   IMM (1),d2      |
2078
        roxrl   IMM (1),d3      |
2079
        roxrl   IMM (1),d6      |
2080
        roxrl   IMM (1),d7      |
2081
        cmpw    IMM (1),d4      | is the exponent 1 already?
2082
#else
2083
        addl    IMM (1),d4      | adjust the exponent
2084
        lsrl    IMM (1),d7
2085
        btst    IMM (0),d6
2086
        beq     13f
2087
        bset    IMM (31),d7
2088
13:     lsrl    IMM (1),d6
2089
        btst    IMM (0),d3
2090
        beq     14f
2091
        bset    IMM (31),d6
2092
14:     lsrl    IMM (1),d3
2093
        btst    IMM (0),d2
2094
        beq     10f
2095
        bset    IMM (31),d3
2096
10:     lsrl    IMM (1),d2
2097
        btst    IMM (0),d1
2098
        beq     11f
2099
        bset    IMM (31),d2
2100
11:     lsrl    IMM (1),d1
2101
        btst    IMM (0),d0
2102
        beq     12f
2103
        bset    IMM (31),d1
2104
12:     lsrl    IMM (1),d0
2105
        cmpl    IMM (1),d4      | is the exponent 1 already?
2106
#endif
2107
        beq     2f              | if not loop back
2108
        bra     1b              |
2109
        bra     Ld$underflow    | safety check, shouldn't execute '
2110
2:      orl     d6,d2           | this is a trick so we don't lose  '
2111
        orl     d7,d3           | the bits which were flushed right
2112
        movel   a0,d7           | get back sign bit into d7
2113
| Now call the rounding routine (which takes care of denormalized numbers):
2114
        lea     pc@(Lround$0),a0 | to return from rounding routine
2115
        PICLEA  SYM (_fpCCR),a1 | check the rounding mode
2116
#ifdef __mcoldfire__
2117
        clrl    d6
2118
#endif
2119
        movew   a1@(6),d6       | rounding mode in d6
2120
        beq     Lround$to$nearest
2121
#ifndef __mcoldfire__
2122
        cmpw    IMM (ROUND_TO_PLUS),d6
2123
#else
2124
        cmpl    IMM (ROUND_TO_PLUS),d6
2125
#endif
2126
        bhi     Lround$to$minus
2127
        blt     Lround$to$zero
2128
        bra     Lround$to$plus
2129
Lround$0:
2130
| Here we have a correctly rounded result (either normalized or denormalized).
2131
 
2132
| Here we should have either a normalized number or a denormalized one, and
2133
| the exponent is necessarily larger or equal to 1 (so we don't have to  '
2134
| check again for underflow!). We have to check for overflow or for a
2135
| denormalized number (which also signals underflow).
2136
| Check for overflow (i.e., exponent >= 0x7ff).
2137
#ifndef __mcoldfire__
2138
        cmpw    IMM (0x07ff),d4
2139
#else
2140
        cmpl    IMM (0x07ff),d4
2141
#endif
2142
        bge     Ld$overflow
2143
| Now check for a denormalized number (exponent==0):
2144
        movew   d4,d4
2145
        beq     Ld$den
2146
1:
2147
| Put back the exponents and sign and return.
2148
#ifndef __mcoldfire__
2149
        lslw    IMM (4),d4      | exponent back to fourth byte
2150
#else
2151
        lsll    IMM (4),d4      | exponent back to fourth byte
2152
#endif
2153
        bclr    IMM (DBL_MANT_DIG-32-1),d0
2154
        swap    d0              | and put back exponent
2155
#ifndef __mcoldfire__
2156
        orw     d4,d0           |
2157
#else
2158
        orl     d4,d0           |
2159
#endif
2160
        swap    d0              |
2161
        orl     d7,d0           | and sign also
2162
 
2163
        PICLEA  SYM (_fpCCR),a0
2164
        movew   IMM (0),a0@
2165
#ifndef __mcoldfire__
2166
        moveml  sp@+,d2-d7
2167
#else
2168
        moveml  sp@,d2-d7
2169
        | XXX if frame pointer is ever removed, stack pointer must
2170
        | be adjusted here.
2171
#endif
2172
        unlk    a6
2173
        rts
2174
 
2175
|=============================================================================
2176
|                              __negdf2
2177
|=============================================================================
2178
 
2179
| double __negdf2(double, double);
2180
SYM (__negdf2):
2181
#ifndef __mcoldfire__
2182
        link    a6,IMM (0)
2183
        moveml  d2-d7,sp@-
2184
#else
2185
        link    a6,IMM (-24)
2186
        moveml  d2-d7,sp@
2187
#endif
2188
        moveq   IMM (NEGATE),d5
2189
        movel   a6@(8),d0       | get number to negate in d0-d1
2190
        movel   a6@(12),d1      |
2191
        bchg    IMM (31),d0     | negate
2192
        movel   d0,d2           | make a positive copy (for the tests)
2193
        bclr    IMM (31),d2     |
2194
        movel   d2,d4           | check for zero
2195
        orl     d1,d4           |
2196
        beq     2f              | if zero (either sign) return +zero
2197
        cmpl    IMM (0x7ff00000),d2 | compare to +INFINITY
2198
        blt     1f              | if finite, return
2199
        bhi     Ld$inop         | if larger (fraction not zero) is NaN
2200
        tstl    d1              | if d2 == 0x7ff00000 check d1
2201
        bne     Ld$inop         |
2202
        movel   d0,d7           | else get sign and return INFINITY
2203
        andl    IMM (0x80000000),d7
2204
        bra     Ld$infty
2205
1:      PICLEA  SYM (_fpCCR),a0
2206
        movew   IMM (0),a0@
2207
#ifndef __mcoldfire__
2208
        moveml  sp@+,d2-d7
2209
#else
2210
        moveml  sp@,d2-d7
2211
        | XXX if frame pointer is ever removed, stack pointer must
2212
        | be adjusted here.
2213
#endif
2214
        unlk    a6
2215
        rts
2216
2:      bclr    IMM (31),d0
2217
        bra     1b
2218
 
2219
|=============================================================================
2220
|                              __cmpdf2
2221
|=============================================================================
2222
 
2223
GREATER =  1
2224
LESS    = -1
2225
EQUAL   =  0
2226
 
2227
| int __cmpdf2_internal(double, double, int);
2228
SYM (__cmpdf2_internal):
2229
#ifndef __mcoldfire__
2230
        link    a6,IMM (0)
2231
        moveml  d2-d7,sp@-      | save registers
2232
#else
2233
        link    a6,IMM (-24)
2234
        moveml  d2-d7,sp@
2235
#endif
2236
        moveq   IMM (COMPARE),d5
2237
        movel   a6@(8),d0       | get first operand
2238
        movel   a6@(12),d1      |
2239
        movel   a6@(16),d2      | get second operand
2240
        movel   a6@(20),d3      |
2241
| First check if a and/or b are (+/-) zero and in that case clear
2242
| the sign bit.
2243
        movel   d0,d6           | copy signs into d6 (a) and d7(b)
2244
        bclr    IMM (31),d0     | and clear signs in d0 and d2
2245
        movel   d2,d7           |
2246
        bclr    IMM (31),d2     |
2247
        cmpl    IMM (0x7ff00000),d0 | check for a == NaN
2248
        bhi     Lcmpd$inop              | if d0 > 0x7ff00000, a is NaN
2249
        beq     Lcmpdf$a$nf     | if equal can be INFINITY, so check d1
2250
        movel   d0,d4           | copy into d4 to test for zero
2251
        orl     d1,d4           |
2252
        beq     Lcmpdf$a$0      |
2253
Lcmpdf$0:
2254
        cmpl    IMM (0x7ff00000),d2 | check for b == NaN
2255
        bhi     Lcmpd$inop              | if d2 > 0x7ff00000, b is NaN
2256
        beq     Lcmpdf$b$nf     | if equal can be INFINITY, so check d3
2257
        movel   d2,d4           |
2258
        orl     d3,d4           |
2259
        beq     Lcmpdf$b$0      |
2260
Lcmpdf$1:
2261
| Check the signs
2262
        eorl    d6,d7
2263
        bpl     1f
2264
| If the signs are not equal check if a >= 0
2265
        tstl    d6
2266
        bpl     Lcmpdf$a$gt$b   | if (a >= 0 && b < 0) => a > b
2267
        bmi     Lcmpdf$b$gt$a   | if (a < 0 && b >= 0) => a < b
2268
1:
2269
| If the signs are equal check for < 0
2270
        tstl    d6
2271
        bpl     1f
2272
| If both are negative exchange them
2273
#ifndef __mcoldfire__
2274
        exg     d0,d2
2275
        exg     d1,d3
2276
#else
2277
        movel   d0,d7
2278
        movel   d2,d0
2279
        movel   d7,d2
2280
        movel   d1,d7
2281
        movel   d3,d1
2282
        movel   d7,d3
2283
#endif
2284
1:
2285
| Now that they are positive we just compare them as longs (does this also
2286
| work for denormalized numbers?).
2287
        cmpl    d0,d2
2288
        bhi     Lcmpdf$b$gt$a   | |b| > |a|
2289
        bne     Lcmpdf$a$gt$b   | |b| < |a|
2290
| If we got here d0 == d2, so we compare d1 and d3.
2291
        cmpl    d1,d3
2292
        bhi     Lcmpdf$b$gt$a   | |b| > |a|
2293
        bne     Lcmpdf$a$gt$b   | |b| < |a|
2294
| If we got here a == b.
2295
        movel   IMM (EQUAL),d0
2296
#ifndef __mcoldfire__
2297
        moveml  sp@+,d2-d7      | put back the registers
2298
#else
2299
        moveml  sp@,d2-d7
2300
        | XXX if frame pointer is ever removed, stack pointer must
2301
        | be adjusted here.
2302
#endif
2303
        unlk    a6
2304
        rts
2305
Lcmpdf$a$gt$b:
2306
        movel   IMM (GREATER),d0
2307
#ifndef __mcoldfire__
2308
        moveml  sp@+,d2-d7      | put back the registers
2309
#else
2310
        moveml  sp@,d2-d7
2311
        | XXX if frame pointer is ever removed, stack pointer must
2312
        | be adjusted here.
2313
#endif
2314
        unlk    a6
2315
        rts
2316
Lcmpdf$b$gt$a:
2317
        movel   IMM (LESS),d0
2318
#ifndef __mcoldfire__
2319
        moveml  sp@+,d2-d7      | put back the registers
2320
#else
2321
        moveml  sp@,d2-d7
2322
        | XXX if frame pointer is ever removed, stack pointer must
2323
        | be adjusted here.
2324
#endif
2325
        unlk    a6
2326
        rts
2327
 
2328
Lcmpdf$a$0:
2329
        bclr    IMM (31),d6
2330
        bra     Lcmpdf$0
2331
Lcmpdf$b$0:
2332
        bclr    IMM (31),d7
2333
        bra     Lcmpdf$1
2334
 
2335
Lcmpdf$a$nf:
2336
        tstl    d1
2337
        bne     Ld$inop
2338
        bra     Lcmpdf$0
2339
 
2340
Lcmpdf$b$nf:
2341
        tstl    d3
2342
        bne     Ld$inop
2343
        bra     Lcmpdf$1
2344
 
2345
Lcmpd$inop:
2346
        movl    a6@(24),d0
2347
        moveq   IMM (INEXACT_RESULT+INVALID_OPERATION),d7
2348
        moveq   IMM (DOUBLE_FLOAT),d6
2349
        PICJUMP $_exception_handler
2350
 
2351
| int __cmpdf2(double, double);
2352
SYM (__cmpdf2):
2353
        link    a6,IMM (0)
2354
        pea     1
2355
        movl    a6@(20),sp@-
2356
        movl    a6@(16),sp@-
2357
        movl    a6@(12),sp@-
2358
        movl    a6@(8),sp@-
2359
        bsr     SYM (__cmpdf2_internal)
2360
        unlk    a6
2361
        rts
2362
 
2363
|=============================================================================
2364
|                           rounding routines
2365
|=============================================================================
2366
 
2367
| The rounding routines expect the number to be normalized in registers
2368
| d0-d1-d2-d3, with the exponent in register d4. They assume that the
2369
| exponent is larger or equal to 1. They return a properly normalized number
2370
| if possible, and a denormalized number otherwise. The exponent is returned
2371
| in d4.
2372
 
2373
Lround$to$nearest:
2374
| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
2375
| Here we assume that the exponent is not too small (this should be checked
2376
| before entering the rounding routine), but the number could be denormalized.
2377
 
2378
| Check for denormalized numbers:
2379
1:      btst    IMM (DBL_MANT_DIG-32),d0
2380
        bne     2f              | if set the number is normalized
2381
| Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent
2382
| is one (remember that a denormalized number corresponds to an
2383
| exponent of -D_BIAS+1).
2384
#ifndef __mcoldfire__
2385
        cmpw    IMM (1),d4      | remember that the exponent is at least one
2386
#else
2387
        cmpl    IMM (1),d4      | remember that the exponent is at least one
2388
#endif
2389
        beq     2f              | an exponent of one means denormalized
2390
        addl    d3,d3           | else shift and adjust the exponent
2391
        addxl   d2,d2           |
2392
        addxl   d1,d1           |
2393
        addxl   d0,d0           |
2394
#ifndef __mcoldfire__
2395
        dbra    d4,1b           |
2396
#else
2397
        subql   IMM (1), d4
2398
        bpl     1b
2399
#endif
2400
2:
2401
| Now round: we do it as follows: after the shifting we can write the
2402
| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
2403
| If delta < 1, do nothing. If delta > 1, add 1 to f.
2404
| If delta == 1, we make sure the rounded number will be even (odd?)
2405
| (after shifting).
2406
        btst    IMM (0),d1      | is delta < 1?
2407
        beq     2f              | if so, do not do anything
2408
        orl     d2,d3           | is delta == 1?
2409
        bne     1f              | if so round to even
2410
        movel   d1,d3           |
2411
        andl    IMM (2),d3      | bit 1 is the last significant bit
2412
        movel   IMM (0),d2      |
2413
        addl    d3,d1           |
2414
        addxl   d2,d0           |
2415
        bra     2f              |
2416
1:      movel   IMM (1),d3      | else add 1
2417
        movel   IMM (0),d2      |
2418
        addl    d3,d1           |
2419
        addxl   d2,d0
2420
| Shift right once (because we used bit #DBL_MANT_DIG-32!).
2421
2:
2422
#ifndef __mcoldfire__
2423
        lsrl    IMM (1),d0
2424
        roxrl   IMM (1),d1
2425
#else
2426
        lsrl    IMM (1),d1
2427
        btst    IMM (0),d0
2428
        beq     10f
2429
        bset    IMM (31),d1
2430
10:     lsrl    IMM (1),d0
2431
#endif
2432
 
2433
| Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a
2434
| 'fraction overflow' ...).
2435
        btst    IMM (DBL_MANT_DIG-32),d0
2436
        beq     1f
2437
#ifndef __mcoldfire__
2438
        lsrl    IMM (1),d0
2439
        roxrl   IMM (1),d1
2440
        addw    IMM (1),d4
2441
#else
2442
        lsrl    IMM (1),d1
2443
        btst    IMM (0),d0
2444
        beq     10f
2445
        bset    IMM (31),d1
2446
10:     lsrl    IMM (1),d0
2447
        addl    IMM (1),d4
2448
#endif
2449
1:
2450
| If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we
2451
| have to put the exponent to zero and return a denormalized number.
2452
        btst    IMM (DBL_MANT_DIG-32-1),d0
2453
        beq     1f
2454
        jmp     a0@
2455
1:      movel   IMM (0),d4
2456
        jmp     a0@
2457
 
2458
Lround$to$zero:
2459
Lround$to$plus:
2460
Lround$to$minus:
2461
        jmp     a0@
2462
#endif /* L_double */
2463
 
2464
#ifdef  L_float
2465
 
2466
        .globl  SYM (_fpCCR)
2467
        .globl  $_exception_handler
2468
 
2469
QUIET_NaN    = 0xffffffff
2470
SIGNL_NaN    = 0x7f800001
2471
INFINITY     = 0x7f800000
2472
 
2473
F_MAX_EXP      = 0xff
2474
F_BIAS         = 126
2475
FLT_MAX_EXP    = F_MAX_EXP - F_BIAS
2476
FLT_MIN_EXP    = 1 - F_BIAS
2477
FLT_MANT_DIG   = 24
2478
 
2479
INEXACT_RESULT          = 0x0001
2480
UNDERFLOW               = 0x0002
2481
OVERFLOW                = 0x0004
2482
DIVIDE_BY_ZERO          = 0x0008
2483
INVALID_OPERATION       = 0x0010
2484
 
2485
SINGLE_FLOAT = 1
2486
 
2487
NOOP         = 0
2488
ADD          = 1
2489
MULTIPLY     = 2
2490
DIVIDE       = 3
2491
NEGATE       = 4
2492
COMPARE      = 5
2493
EXTENDSFDF   = 6
2494
TRUNCDFSF    = 7
2495
 
2496
UNKNOWN           = -1
2497
ROUND_TO_NEAREST  = 0 | round result to nearest representable value
2498
ROUND_TO_ZERO     = 1 | round result towards zero
2499
ROUND_TO_PLUS     = 2 | round result towards plus infinity
2500
ROUND_TO_MINUS    = 3 | round result towards minus infinity
2501
 
2502
| Entry points:
2503
 
2504
        .globl SYM (__addsf3)
2505
        .globl SYM (__subsf3)
2506
        .globl SYM (__mulsf3)
2507
        .globl SYM (__divsf3)
2508
        .globl SYM (__negsf2)
2509
        .globl SYM (__cmpsf2)
2510
        .globl SYM (__cmpsf2_internal)
2511
 
2512
| These are common routines to return and signal exceptions.
2513
 
2514
        .text
2515
        .even
2516
 
2517
Lf$den:
2518
| Return and signal a denormalized number
2519
        orl     d7,d0
2520
        moveq   IMM (INEXACT_RESULT+UNDERFLOW),d7
2521
        moveq   IMM (SINGLE_FLOAT),d6
2522
        PICJUMP $_exception_handler
2523
 
2524
Lf$infty:
2525
Lf$overflow:
2526
| Return a properly signed INFINITY and set the exception flags
2527
        movel   IMM (INFINITY),d0
2528
        orl     d7,d0
2529
        moveq   IMM (INEXACT_RESULT+OVERFLOW),d7
2530
        moveq   IMM (SINGLE_FLOAT),d6
2531
        PICJUMP $_exception_handler
2532
 
2533
Lf$underflow:
2534
| Return 0 and set the exception flags
2535
        moveq   IMM (0),d0
2536
        moveq   IMM (INEXACT_RESULT+UNDERFLOW),d7
2537
        moveq   IMM (SINGLE_FLOAT),d6
2538
        PICJUMP $_exception_handler
2539
 
2540
Lf$inop:
2541
| Return a quiet NaN and set the exception flags
2542
        movel   IMM (QUIET_NaN),d0
2543
        moveq   IMM (INEXACT_RESULT+INVALID_OPERATION),d7
2544
        moveq   IMM (SINGLE_FLOAT),d6
2545
        PICJUMP $_exception_handler
2546
 
2547
Lf$div$0:
2548
| Return a properly signed INFINITY and set the exception flags
2549
        movel   IMM (INFINITY),d0
2550
        orl     d7,d0
2551
        moveq   IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
2552
        moveq   IMM (SINGLE_FLOAT),d6
2553
        PICJUMP $_exception_handler
2554
 
2555
|=============================================================================
2556
|=============================================================================
2557
|                         single precision routines
2558
|=============================================================================
2559
|=============================================================================
2560
 
2561
| A single precision floating point number (float) has the format:
2562
|
2563
| struct _float {
2564
|  unsigned int sign      : 1;  /* sign bit */
2565
|  unsigned int exponent  : 8;  /* exponent, shifted by 126 */
2566
|  unsigned int fraction  : 23; /* fraction */
2567
| } float;
2568
|
2569
| Thus sizeof(float) = 4 (32 bits).
2570
|
2571
| All the routines are callable from C programs, and return the result
2572
| in the single register d0. They also preserve all registers except
2573
| d0-d1 and a0-a1.
2574
 
2575
|=============================================================================
2576
|                              __subsf3
2577
|=============================================================================
2578
 
2579
| float __subsf3(float, float);
2580
SYM (__subsf3):
2581
        bchg    IMM (31),sp@(8) | change sign of second operand
2582
                                | and fall through
2583
|=============================================================================
2584
|                              __addsf3
2585
|=============================================================================
2586
 
2587
| float __addsf3(float, float);
2588
SYM (__addsf3):
2589
#ifndef __mcoldfire__
2590
        link    a6,IMM (0)      | everything will be done in registers
2591
        moveml  d2-d7,sp@-      | save all data registers but d0-d1
2592
#else
2593
        link    a6,IMM (-24)
2594
        moveml  d2-d7,sp@
2595
#endif
2596
        movel   a6@(8),d0       | get first operand
2597
        movel   a6@(12),d1      | get second operand
2598
        movel   d0,a0           | get d0's sign bit '
2599
        addl    d0,d0           | check and clear sign bit of a
2600
        beq     Laddsf$b        | if zero return second operand
2601
        movel   d1,a1           | save b's sign bit '
2602
        addl    d1,d1           | get rid of sign bit
2603
        beq     Laddsf$a        | if zero return first operand
2604
 
2605
| Get the exponents and check for denormalized and/or infinity.
2606
 
2607
        movel   IMM (0x00ffffff),d4     | mask to get fraction
2608
        movel   IMM (0x01000000),d5     | mask to put hidden bit back
2609
 
2610
        movel   d0,d6           | save a to get exponent
2611
        andl    d4,d0           | get fraction in d0
2612
        notl    d4              | make d4 into a mask for the exponent
2613
        andl    d4,d6           | get exponent in d6
2614
        beq     Laddsf$a$den    | branch if a is denormalized
2615
        cmpl    d4,d6           | check for INFINITY or NaN
2616
        beq     Laddsf$nf
2617
        swap    d6              | put exponent into first word
2618
        orl     d5,d0           | and put hidden bit back
2619
Laddsf$1:
2620
| Now we have a's exponent in d6 (second byte) and the mantissa in d0. '
2621
        movel   d1,d7           | get exponent in d7
2622
        andl    d4,d7           |
2623
        beq     Laddsf$b$den    | branch if b is denormalized
2624
        cmpl    d4,d7           | check for INFINITY or NaN
2625
        beq     Laddsf$nf
2626
        swap    d7              | put exponent into first word
2627
        notl    d4              | make d4 into a mask for the fraction
2628
        andl    d4,d1           | get fraction in d1
2629
        orl     d5,d1           | and put hidden bit back
2630
Laddsf$2:
2631
| Now we have b's exponent in d7 (second byte) and the mantissa in d1. '
2632
 
2633
| Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we
2634
| shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra
2635
| bit).
2636
 
2637
        movel   d1,d2           | move b to d2, since we want to use
2638
                                | two registers to do the sum
2639
        movel   IMM (0),d1      | and clear the new ones
2640
        movel   d1,d3           |
2641
 
2642
| Here we shift the numbers in registers d0 and d1 so the exponents are the
2643
| same, and put the largest exponent in d6. Note that we are using two
2644
| registers for each number (see the discussion by D. Knuth in "Seminumerical
2645
| Algorithms").
2646
#ifndef __mcoldfire__
2647
        cmpw    d6,d7           | compare exponents
2648
#else
2649
        cmpl    d6,d7           | compare exponents
2650
#endif
2651
        beq     Laddsf$3        | if equal don't shift '
2652
        bhi     5f              | branch if second exponent largest
2653
1:
2654
        subl    d6,d7           | keep the largest exponent
2655
        negl    d7
2656
#ifndef __mcoldfire__
2657
        lsrw    IMM (8),d7      | put difference in lower byte
2658
#else
2659
        lsrl    IMM (8),d7      | put difference in lower byte
2660
#endif
2661
| if difference is too large we don't shift (actually, we can just exit) '
2662
#ifndef __mcoldfire__
2663
        cmpw    IMM (FLT_MANT_DIG+2),d7
2664
#else
2665
        cmpl    IMM (FLT_MANT_DIG+2),d7
2666
#endif
2667
        bge     Laddsf$b$small
2668
#ifndef __mcoldfire__
2669
        cmpw    IMM (16),d7     | if difference >= 16 swap
2670
#else
2671
        cmpl    IMM (16),d7     | if difference >= 16 swap
2672
#endif
2673
        bge     4f
2674
2:
2675
#ifndef __mcoldfire__
2676
        subw    IMM (1),d7
2677
#else
2678
        subql   IMM (1), d7
2679
#endif
2680
3:
2681
#ifndef __mcoldfire__
2682
        lsrl    IMM (1),d2      | shift right second operand
2683
        roxrl   IMM (1),d3
2684
        dbra    d7,3b
2685
#else
2686
        lsrl    IMM (1),d3
2687
        btst    IMM (0),d2
2688
        beq     10f
2689
        bset    IMM (31),d3
2690
10:     lsrl    IMM (1),d2
2691
        subql   IMM (1), d7
2692
        bpl     3b
2693
#endif
2694
        bra     Laddsf$3
2695
4:
2696
        movew   d2,d3
2697
        swap    d3
2698
        movew   d3,d2
2699
        swap    d2
2700
#ifndef __mcoldfire__
2701
        subw    IMM (16),d7
2702
#else
2703
        subl    IMM (16),d7
2704
#endif
2705
        bne     2b              | if still more bits, go back to normal case
2706
        bra     Laddsf$3
2707
5:
2708
#ifndef __mcoldfire__
2709
        exg     d6,d7           | exchange the exponents
2710
#else
2711
        eorl    d6,d7
2712
        eorl    d7,d6
2713
        eorl    d6,d7
2714
#endif
2715
        subl    d6,d7           | keep the largest exponent
2716
        negl    d7              |
2717
#ifndef __mcoldfire__
2718
        lsrw    IMM (8),d7      | put difference in lower byte
2719
#else
2720
        lsrl    IMM (8),d7      | put difference in lower byte
2721
#endif
2722
| if difference is too large we don't shift (and exit!) '
2723
#ifndef __mcoldfire__
2724
        cmpw    IMM (FLT_MANT_DIG+2),d7
2725
#else
2726
        cmpl    IMM (FLT_MANT_DIG+2),d7
2727
#endif
2728
        bge     Laddsf$a$small
2729
#ifndef __mcoldfire__
2730
        cmpw    IMM (16),d7     | if difference >= 16 swap
2731
#else
2732
        cmpl    IMM (16),d7     | if difference >= 16 swap
2733
#endif
2734
        bge     8f
2735
6:
2736
#ifndef __mcoldfire__
2737
        subw    IMM (1),d7
2738
#else
2739
        subl    IMM (1),d7
2740
#endif
2741
7:
2742
#ifndef __mcoldfire__
2743
        lsrl    IMM (1),d0      | shift right first operand
2744
        roxrl   IMM (1),d1
2745
        dbra    d7,7b
2746
#else
2747
        lsrl    IMM (1),d1
2748
        btst    IMM (0),d0
2749
        beq     10f
2750
        bset    IMM (31),d1
2751
10:     lsrl    IMM (1),d0
2752
        subql   IMM (1),d7
2753
        bpl     7b
2754
#endif
2755
        bra     Laddsf$3
2756
8:
2757
        movew   d0,d1
2758
        swap    d1
2759
        movew   d1,d0
2760
        swap    d0
2761
#ifndef __mcoldfire__
2762
        subw    IMM (16),d7
2763
#else
2764
        subl    IMM (16),d7
2765
#endif
2766
        bne     6b              | if still more bits, go back to normal case
2767
                                | otherwise we fall through
2768
 
2769
| Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the
2770
| signs are stored in a0 and a1).
2771
 
2772
Laddsf$3:
2773
| Here we have to decide whether to add or subtract the numbers
2774
#ifndef __mcoldfire__
2775
        exg     d6,a0           | get signs back
2776
        exg     d7,a1           | and save the exponents
2777
#else
2778
        movel   d6,d4
2779
        movel   a0,d6
2780
        movel   d4,a0
2781
        movel   d7,d4
2782
        movel   a1,d7
2783
        movel   d4,a1
2784
#endif
2785
        eorl    d6,d7           | combine sign bits
2786
        bmi     Lsubsf$0        | if negative a and b have opposite
2787
                                | sign so we actually subtract the
2788
                                | numbers
2789
 
2790
| Here we have both positive or both negative
2791
#ifndef __mcoldfire__
2792
        exg     d6,a0           | now we have the exponent in d6
2793
#else
2794
        movel   d6,d4
2795
        movel   a0,d6
2796
        movel   d4,a0
2797
#endif
2798
        movel   a0,d7           | and sign in d7
2799
        andl    IMM (0x80000000),d7
2800
| Here we do the addition.
2801
        addl    d3,d1
2802
        addxl   d2,d0
2803
| Note: now we have d2, d3, d4 and d5 to play with!
2804
 
2805
| Put the exponent, in the first byte, in d2, to use the "standard" rounding
2806
| routines:
2807
        movel   d6,d2
2808
#ifndef __mcoldfire__
2809
        lsrw    IMM (8),d2
2810
#else
2811
        lsrl    IMM (8),d2
2812
#endif
2813
 
2814
| Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider
2815
| the case of denormalized numbers in the rounding routine itself).
2816
| As in the addition (not in the subtraction!) we could have set
2817
| one more bit we check this:
2818
        btst    IMM (FLT_MANT_DIG+1),d0
2819
        beq     1f
2820
#ifndef __mcoldfire__
2821
        lsrl    IMM (1),d0
2822
        roxrl   IMM (1),d1
2823
#else
2824
        lsrl    IMM (1),d1
2825
        btst    IMM (0),d0
2826
        beq     10f
2827
        bset    IMM (31),d1
2828
10:     lsrl    IMM (1),d0
2829
#endif
2830
        addl    IMM (1),d2
2831
1:
2832
        lea     pc@(Laddsf$4),a0 | to return from rounding routine
2833
        PICLEA  SYM (_fpCCR),a1 | check the rounding mode
2834
#ifdef __mcoldfire__
2835
        clrl    d6
2836
#endif
2837
        movew   a1@(6),d6       | rounding mode in d6
2838
        beq     Lround$to$nearest
2839
#ifndef __mcoldfire__
2840
        cmpw    IMM (ROUND_TO_PLUS),d6
2841
#else
2842
        cmpl    IMM (ROUND_TO_PLUS),d6
2843
#endif
2844
        bhi     Lround$to$minus
2845
        blt     Lround$to$zero
2846
        bra     Lround$to$plus
2847
Laddsf$4:
2848
| Put back the exponent, but check for overflow.
2849
#ifndef __mcoldfire__
2850
        cmpw    IMM (0xff),d2
2851
#else
2852
        cmpl    IMM (0xff),d2
2853
#endif
2854
        bhi     1f
2855
        bclr    IMM (FLT_MANT_DIG-1),d0
2856
#ifndef __mcoldfire__
2857
        lslw    IMM (7),d2
2858
#else
2859
        lsll    IMM (7),d2
2860
#endif
2861
        swap    d2
2862
        orl     d2,d0
2863
        bra     Laddsf$ret
2864
1:
2865
        moveq   IMM (ADD),d5
2866
        bra     Lf$overflow
2867
 
2868
Lsubsf$0:
2869
| We are here if a > 0 and b < 0 (sign bits cleared).
2870
| Here we do the subtraction.
2871
        movel   d6,d7           | put sign in d7
2872
        andl    IMM (0x80000000),d7
2873
 
2874
        subl    d3,d1           | result in d0-d1
2875
        subxl   d2,d0           |
2876
        beq     Laddsf$ret      | if zero just exit
2877
        bpl     1f              | if positive skip the following
2878
        bchg    IMM (31),d7     | change sign bit in d7
2879
        negl    d1
2880
        negxl   d0
2881
1:
2882
#ifndef __mcoldfire__
2883
        exg     d2,a0           | now we have the exponent in d2
2884
        lsrw    IMM (8),d2      | put it in the first byte
2885
#else
2886
        movel   d2,d4
2887
        movel   a0,d2
2888
        movel   d4,a0
2889
        lsrl    IMM (8),d2      | put it in the first byte
2890
#endif
2891
 
2892
| Now d0-d1 is positive and the sign bit is in d7.
2893
 
2894
| Note that we do not have to normalize, since in the subtraction bit
2895
| #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by
2896
| the rounding routines themselves.
2897
        lea     pc@(Lsubsf$1),a0 | to return from rounding routine
2898
        PICLEA  SYM (_fpCCR),a1 | check the rounding mode
2899
#ifdef __mcoldfire__
2900
        clrl    d6
2901
#endif
2902
        movew   a1@(6),d6       | rounding mode in d6
2903
        beq     Lround$to$nearest
2904
#ifndef __mcoldfire__
2905
        cmpw    IMM (ROUND_TO_PLUS),d6
2906
#else
2907
        cmpl    IMM (ROUND_TO_PLUS),d6
2908
#endif
2909
        bhi     Lround$to$minus
2910
        blt     Lround$to$zero
2911
        bra     Lround$to$plus
2912
Lsubsf$1:
2913
| Put back the exponent (we can't have overflow!). '
2914
        bclr    IMM (FLT_MANT_DIG-1),d0
2915
#ifndef __mcoldfire__
2916
        lslw    IMM (7),d2
2917
#else
2918
        lsll    IMM (7),d2
2919
#endif
2920
        swap    d2
2921
        orl     d2,d0
2922
        bra     Laddsf$ret
2923
 
2924
| If one of the numbers was too small (difference of exponents >=
2925
| FLT_MANT_DIG+2) we return the other (and now we don't have to '
2926
| check for finiteness or zero).
2927
Laddsf$a$small:
2928
        movel   a6@(12),d0
2929
        PICLEA  SYM (_fpCCR),a0
2930
        movew   IMM (0),a0@
2931
#ifndef __mcoldfire__
2932
        moveml  sp@+,d2-d7      | restore data registers
2933
#else
2934
        moveml  sp@,d2-d7
2935
        | XXX if frame pointer is ever removed, stack pointer must
2936
        | be adjusted here.
2937
#endif
2938
        unlk    a6              | and return
2939
        rts
2940
 
2941
Laddsf$b$small:
2942
        movel   a6@(8),d0
2943
        PICLEA  SYM (_fpCCR),a0
2944
        movew   IMM (0),a0@
2945
#ifndef __mcoldfire__
2946
        moveml  sp@+,d2-d7      | restore data registers
2947
#else
2948
        moveml  sp@,d2-d7
2949
        | XXX if frame pointer is ever removed, stack pointer must
2950
        | be adjusted here.
2951
#endif
2952
        unlk    a6              | and return
2953
        rts
2954
 
2955
| If the numbers are denormalized remember to put exponent equal to 1.
2956
 
2957
Laddsf$a$den:
2958
        movel   d5,d6           | d5 contains 0x01000000
2959
        swap    d6
2960
        bra     Laddsf$1
2961
 
2962
Laddsf$b$den:
2963
        movel   d5,d7
2964
        swap    d7
2965
        notl    d4              | make d4 into a mask for the fraction
2966
                                | (this was not executed after the jump)
2967
        bra     Laddsf$2
2968
 
2969
| The rest is mainly code for the different results which can be
2970
| returned (checking always for +/-INFINITY and NaN).
2971
 
2972
Laddsf$b:
2973
| Return b (if a is zero).
2974
        movel   a6@(12),d0
2975
        cmpl    IMM (0x80000000),d0     | Check if b is -0
2976
        bne     1f
2977
        movel   a0,d7
2978
        andl    IMM (0x80000000),d7     | Use the sign of a
2979
        clrl    d0
2980
        bra     Laddsf$ret
2981
Laddsf$a:
2982
| Return a (if b is zero).
2983
        movel   a6@(8),d0
2984
1:
2985
        moveq   IMM (ADD),d5
2986
| We have to check for NaN and +/-infty.
2987
        movel   d0,d7
2988
        andl    IMM (0x80000000),d7     | put sign in d7
2989
        bclr    IMM (31),d0             | clear sign
2990
        cmpl    IMM (INFINITY),d0       | check for infty or NaN
2991
        bge     2f
2992
        movel   d0,d0           | check for zero (we do this because we don't '
2993
        bne     Laddsf$ret      | want to return -0 by mistake
2994
        bclr    IMM (31),d7     | if zero be sure to clear sign
2995
        bra     Laddsf$ret      | if everything OK just return
2996
2:
2997
| The value to be returned is either +/-infty or NaN
2998
        andl    IMM (0x007fffff),d0     | check for NaN
2999
        bne     Lf$inop                 | if mantissa not zero is NaN
3000
        bra     Lf$infty
3001
 
3002
Laddsf$ret:
3003
| Normal exit (a and b nonzero, result is not NaN nor +/-infty).
3004
| We have to clear the exception flags (just the exception type).
3005
        PICLEA  SYM (_fpCCR),a0
3006
        movew   IMM (0),a0@
3007
        orl     d7,d0           | put sign bit
3008
#ifndef __mcoldfire__
3009
        moveml  sp@+,d2-d7      | restore data registers
3010
#else
3011
        moveml  sp@,d2-d7
3012
        | XXX if frame pointer is ever removed, stack pointer must
3013
        | be adjusted here.
3014
#endif
3015
        unlk    a6              | and return
3016
        rts
3017
 
3018
Laddsf$ret$den:
3019
| Return a denormalized number (for addition we don't signal underflow) '
3020
        lsrl    IMM (1),d0      | remember to shift right back once
3021
        bra     Laddsf$ret      | and return
3022
 
3023
| Note: when adding two floats of the same sign if either one is
3024
| NaN we return NaN without regard to whether the other is finite or
3025
| not. When subtracting them (i.e., when adding two numbers of
3026
| opposite signs) things are more complicated: if both are INFINITY
3027
| we return NaN, if only one is INFINITY and the other is NaN we return
3028
| NaN, but if it is finite we return INFINITY with the corresponding sign.
3029
 
3030
Laddsf$nf:
3031
        moveq   IMM (ADD),d5
3032
| This could be faster but it is not worth the effort, since it is not
3033
| executed very often. We sacrifice speed for clarity here.
3034
        movel   a6@(8),d0       | get the numbers back (remember that we
3035
        movel   a6@(12),d1      | did some processing already)
3036
        movel   IMM (INFINITY),d4 | useful constant (INFINITY)
3037
        movel   d0,d2           | save sign bits
3038
        movel   d1,d3
3039
        bclr    IMM (31),d0     | clear sign bits
3040
        bclr    IMM (31),d1
3041
| We know that one of them is either NaN of +/-INFINITY
3042
| Check for NaN (if either one is NaN return NaN)
3043
        cmpl    d4,d0           | check first a (d0)
3044
        bhi     Lf$inop
3045
        cmpl    d4,d1           | check now b (d1)
3046
        bhi     Lf$inop
3047
| Now comes the check for +/-INFINITY. We know that both are (maybe not
3048
| finite) numbers, but we have to check if both are infinite whether we
3049
| are adding or subtracting them.
3050
        eorl    d3,d2           | to check sign bits
3051
        bmi     1f
3052
        movel   d0,d7
3053
        andl    IMM (0x80000000),d7     | get (common) sign bit
3054
        bra     Lf$infty
3055
1:
3056
| We know one (or both) are infinite, so we test for equality between the
3057
| two numbers (if they are equal they have to be infinite both, so we
3058
| return NaN).
3059
        cmpl    d1,d0           | are both infinite?
3060
        beq     Lf$inop         | if so return NaN
3061
 
3062
        movel   d0,d7
3063
        andl    IMM (0x80000000),d7 | get a's sign bit '
3064
        cmpl    d4,d0           | test now for infinity
3065
        beq     Lf$infty        | if a is INFINITY return with this sign
3066
        bchg    IMM (31),d7     | else we know b is INFINITY and has
3067
        bra     Lf$infty        | the opposite sign
3068
 
3069
|=============================================================================
3070
|                             __mulsf3
3071
|=============================================================================
3072
 
3073
| float __mulsf3(float, float);
3074
SYM (__mulsf3):
3075
#ifndef __mcoldfire__
3076
        link    a6,IMM (0)
3077
        moveml  d2-d7,sp@-
3078
#else
3079
        link    a6,IMM (-24)
3080
        moveml  d2-d7,sp@
3081
#endif
3082
        movel   a6@(8),d0       | get a into d0
3083
        movel   a6@(12),d1      | and b into d1
3084
        movel   d0,d7           | d7 will hold the sign of the product
3085
        eorl    d1,d7           |
3086
        andl    IMM (0x80000000),d7
3087
        movel   IMM (INFINITY),d6       | useful constant (+INFINITY)
3088
        movel   d6,d5                   | another (mask for fraction)
3089
        notl    d5                      |
3090
        movel   IMM (0x00800000),d4     | this is to put hidden bit back
3091
        bclr    IMM (31),d0             | get rid of a's sign bit '
3092
        movel   d0,d2                   |
3093
        beq     Lmulsf$a$0              | branch if a is zero
3094
        bclr    IMM (31),d1             | get rid of b's sign bit '
3095
        movel   d1,d3           |
3096
        beq     Lmulsf$b$0      | branch if b is zero
3097
        cmpl    d6,d0           | is a big?
3098
        bhi     Lmulsf$inop     | if a is NaN return NaN
3099
        beq     Lmulsf$inf      | if a is INFINITY we have to check b
3100
        cmpl    d6,d1           | now compare b with INFINITY
3101
        bhi     Lmulsf$inop     | is b NaN?
3102
        beq     Lmulsf$overflow | is b INFINITY?
3103
| Here we have both numbers finite and nonzero (and with no sign bit).
3104
| Now we get the exponents into d2 and d3.
3105
        andl    d6,d2           | and isolate exponent in d2
3106
        beq     Lmulsf$a$den    | if exponent is zero we have a denormalized
3107
        andl    d5,d0           | and isolate fraction
3108
        orl     d4,d0           | and put hidden bit back
3109
        swap    d2              | I like exponents in the first byte
3110
#ifndef __mcoldfire__
3111
        lsrw    IMM (7),d2      |
3112
#else
3113
        lsrl    IMM (7),d2      |
3114
#endif
3115
Lmulsf$1:                       | number
3116
        andl    d6,d3           |
3117
        beq     Lmulsf$b$den    |
3118
        andl    d5,d1           |
3119
        orl     d4,d1           |
3120
        swap    d3              |
3121
#ifndef __mcoldfire__
3122
        lsrw    IMM (7),d3      |
3123
#else
3124
        lsrl    IMM (7),d3      |
3125
#endif
3126
Lmulsf$2:                       |
3127
#ifndef __mcoldfire__
3128
        addw    d3,d2           | add exponents
3129
        subw    IMM (F_BIAS+1),d2 | and subtract bias (plus one)
3130
#else
3131
        addl    d3,d2           | add exponents
3132
        subl    IMM (F_BIAS+1),d2 | and subtract bias (plus one)
3133
#endif
3134
 
3135
| We are now ready to do the multiplication. The situation is as follows:
3136
| both a and b have bit FLT_MANT_DIG-1 set (even if they were
3137
| denormalized to start with!), which means that in the product
3138
| bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the
3139
| high long) is set.
3140
 
3141
| To do the multiplication let us move the number a little bit around ...
3142
        movel   d1,d6           | second operand in d6
3143
        movel   d0,d5           | first operand in d4-d5
3144
        movel   IMM (0),d4
3145
        movel   d4,d1           | the sums will go in d0-d1
3146
        movel   d4,d0
3147
 
3148
| now bit FLT_MANT_DIG-1 becomes bit 31:
3149
        lsll    IMM (31-FLT_MANT_DIG+1),d6
3150
 
3151
| Start the loop (we loop #FLT_MANT_DIG times):
3152
        moveq   IMM (FLT_MANT_DIG-1),d3
3153
1:      addl    d1,d1           | shift sum
3154
        addxl   d0,d0
3155
        lsll    IMM (1),d6      | get bit bn
3156
        bcc     2f              | if not set skip sum
3157
        addl    d5,d1           | add a
3158
        addxl   d4,d0
3159
2:
3160
#ifndef __mcoldfire__
3161
        dbf     d3,1b           | loop back
3162
#else
3163
        subql   IMM (1),d3
3164
        bpl     1b
3165
#endif
3166
 
3167
| Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG
3168
| (mod 32) of d0 set. The first thing to do now is to normalize it so bit
3169
| FLT_MANT_DIG is set (to do the rounding).
3170
#ifndef __mcoldfire__
3171
        rorl    IMM (6),d1
3172
        swap    d1
3173
        movew   d1,d3
3174
        andw    IMM (0x03ff),d3
3175
        andw    IMM (0xfd00),d1
3176
#else
3177
        movel   d1,d3
3178
        lsll    IMM (8),d1
3179
        addl    d1,d1
3180
        addl    d1,d1
3181
        moveq   IMM (22),d5
3182
        lsrl    d5,d3
3183
        orl     d3,d1
3184
        andl    IMM (0xfffffd00),d1
3185
#endif
3186
        lsll    IMM (8),d0
3187
        addl    d0,d0
3188
        addl    d0,d0
3189
#ifndef __mcoldfire__
3190
        orw     d3,d0
3191
#else
3192
        orl     d3,d0
3193
#endif
3194
 
3195
        moveq   IMM (MULTIPLY),d5
3196
 
3197
        btst    IMM (FLT_MANT_DIG+1),d0
3198
        beq     Lround$exit
3199
#ifndef __mcoldfire__
3200
        lsrl    IMM (1),d0
3201
        roxrl   IMM (1),d1
3202
        addw    IMM (1),d2
3203
#else
3204
        lsrl    IMM (1),d1
3205
        btst    IMM (0),d0
3206
        beq     10f
3207
        bset    IMM (31),d1
3208
10:     lsrl    IMM (1),d0
3209
        addql   IMM (1),d2
3210
#endif
3211
        bra     Lround$exit
3212
 
3213
Lmulsf$inop:
3214
        moveq   IMM (MULTIPLY),d5
3215
        bra     Lf$inop
3216
 
3217
Lmulsf$overflow:
3218
        moveq   IMM (MULTIPLY),d5
3219
        bra     Lf$overflow
3220
 
3221
Lmulsf$inf:
3222
        moveq   IMM (MULTIPLY),d5
3223
| If either is NaN return NaN; else both are (maybe infinite) numbers, so
3224
| return INFINITY with the correct sign (which is in d7).
3225
        cmpl    d6,d1           | is b NaN?
3226
        bhi     Lf$inop         | if so return NaN
3227
        bra     Lf$overflow     | else return +/-INFINITY
3228
 
3229
| If either number is zero return zero, unless the other is +/-INFINITY,
3230
| or NaN, in which case we return NaN.
3231
Lmulsf$b$0:
3232
| Here d1 (==b) is zero.
3233
        movel   a6@(8),d1       | get a again to check for non-finiteness
3234
        bra     1f
3235
Lmulsf$a$0:
3236
        movel   a6@(12),d1      | get b again to check for non-finiteness
3237
1:      bclr    IMM (31),d1     | clear sign bit
3238
        cmpl    IMM (INFINITY),d1 | and check for a large exponent
3239
        bge     Lf$inop         | if b is +/-INFINITY or NaN return NaN
3240
        movel   d7,d0           | else return signed zero
3241
        PICLEA  SYM (_fpCCR),a0 |
3242
        movew   IMM (0),a0@     |
3243
#ifndef __mcoldfire__
3244
        moveml  sp@+,d2-d7      |
3245
#else
3246
        moveml  sp@,d2-d7
3247
        | XXX if frame pointer is ever removed, stack pointer must
3248
        | be adjusted here.
3249
#endif
3250
        unlk    a6              |
3251
        rts                     |
3252
 
3253
| If a number is denormalized we put an exponent of 1 but do not put the
3254
| hidden bit back into the fraction; instead we shift left until bit 23
3255
| (the hidden bit) is set, adjusting the exponent accordingly. We do this
3256
| to ensure that the product of the fractions is close to 1.
3257
Lmulsf$a$den:
3258
        movel   IMM (1),d2
3259
        andl    d5,d0
3260
1:      addl    d0,d0           | shift a left (until bit 23 is set)
3261
#ifndef __mcoldfire__
3262
        subw    IMM (1),d2      | and adjust exponent
3263
#else
3264
        subql   IMM (1),d2      | and adjust exponent
3265
#endif
3266
        btst    IMM (FLT_MANT_DIG-1),d0
3267
        bne     Lmulsf$1        |
3268
        bra     1b              | else loop back
3269
 
3270
Lmulsf$b$den:
3271
        movel   IMM (1),d3
3272
        andl    d5,d1
3273
1:      addl    d1,d1           | shift b left until bit 23 is set
3274
#ifndef __mcoldfire__
3275
        subw    IMM (1),d3      | and adjust exponent
3276
#else
3277
        subql   IMM (1),d3      | and adjust exponent
3278
#endif
3279
        btst    IMM (FLT_MANT_DIG-1),d1
3280
        bne     Lmulsf$2        |
3281
        bra     1b              | else loop back
3282
 
3283
|=============================================================================
3284
|                             __divsf3
3285
|=============================================================================
3286
 
3287
| float __divsf3(float, float);
3288
SYM (__divsf3):
3289
#ifndef __mcoldfire__
3290
        link    a6,IMM (0)
3291
        moveml  d2-d7,sp@-
3292
#else
3293
        link    a6,IMM (-24)
3294
        moveml  d2-d7,sp@
3295
#endif
3296
        movel   a6@(8),d0               | get a into d0
3297
        movel   a6@(12),d1              | and b into d1
3298
        movel   d0,d7                   | d7 will hold the sign of the result
3299
        eorl    d1,d7                   |
3300
        andl    IMM (0x80000000),d7     |
3301
        movel   IMM (INFINITY),d6       | useful constant (+INFINITY)
3302
        movel   d6,d5                   | another (mask for fraction)
3303
        notl    d5                      |
3304
        movel   IMM (0x00800000),d4     | this is to put hidden bit back
3305
        bclr    IMM (31),d0             | get rid of a's sign bit '
3306
        movel   d0,d2                   |
3307
        beq     Ldivsf$a$0              | branch if a is zero
3308
        bclr    IMM (31),d1             | get rid of b's sign bit '
3309
        movel   d1,d3                   |
3310
        beq     Ldivsf$b$0              | branch if b is zero
3311
        cmpl    d6,d0                   | is a big?
3312
        bhi     Ldivsf$inop             | if a is NaN return NaN
3313
        beq     Ldivsf$inf              | if a is INFINITY we have to check b
3314
        cmpl    d6,d1                   | now compare b with INFINITY
3315
        bhi     Ldivsf$inop             | if b is NaN return NaN
3316
        beq     Ldivsf$underflow
3317
| Here we have both numbers finite and nonzero (and with no sign bit).
3318
| Now we get the exponents into d2 and d3 and normalize the numbers to
3319
| ensure that the ratio of the fractions is close to 1. We do this by
3320
| making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set.
3321
        andl    d6,d2           | and isolate exponent in d2
3322
        beq     Ldivsf$a$den    | if exponent is zero we have a denormalized
3323
        andl    d5,d0           | and isolate fraction
3324
        orl     d4,d0           | and put hidden bit back
3325
        swap    d2              | I like exponents in the first byte
3326
#ifndef __mcoldfire__
3327
        lsrw    IMM (7),d2      |
3328
#else
3329
        lsrl    IMM (7),d2      |
3330
#endif
3331
Ldivsf$1:                       |
3332
        andl    d6,d3           |
3333
        beq     Ldivsf$b$den    |
3334
        andl    d5,d1           |
3335
        orl     d4,d1           |
3336
        swap    d3              |
3337
#ifndef __mcoldfire__
3338
        lsrw    IMM (7),d3      |
3339
#else
3340
        lsrl    IMM (7),d3      |
3341
#endif
3342
Ldivsf$2:                       |
3343
#ifndef __mcoldfire__
3344
        subw    d3,d2           | subtract exponents
3345
        addw    IMM (F_BIAS),d2 | and add bias
3346
#else
3347
        subl    d3,d2           | subtract exponents
3348
        addl    IMM (F_BIAS),d2 | and add bias
3349
#endif
3350
 
3351
| We are now ready to do the division. We have prepared things in such a way
3352
| that the ratio of the fractions will be less than 2 but greater than 1/2.
3353
| At this point the registers in use are:
3354
| d0    holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1)
3355
| d1    holds b (second operand, bit FLT_MANT_DIG=1)
3356
| d2    holds the difference of the exponents, corrected by the bias
3357
| d7    holds the sign of the ratio
3358
| d4, d5, d6 hold some constants
3359
        movel   d7,a0           | d6-d7 will hold the ratio of the fractions
3360
        movel   IMM (0),d6      |
3361
        movel   d6,d7
3362
 
3363
        moveq   IMM (FLT_MANT_DIG+1),d3
3364
1:      cmpl    d0,d1           | is a < b?
3365
        bhi     2f              |
3366
        bset    d3,d6           | set a bit in d6
3367
        subl    d1,d0           | if a >= b  a <-- a-b
3368
        beq     3f              | if a is zero, exit
3369
2:      addl    d0,d0           | multiply a by 2
3370
#ifndef __mcoldfire__
3371
        dbra    d3,1b
3372
#else
3373
        subql   IMM (1),d3
3374
        bpl     1b
3375
#endif
3376
 
3377
| Now we keep going to set the sticky bit ...
3378
        moveq   IMM (FLT_MANT_DIG),d3
3379
1:      cmpl    d0,d1
3380
        ble     2f
3381
        addl    d0,d0
3382
#ifndef __mcoldfire__
3383
        dbra    d3,1b
3384
#else
3385
        subql   IMM(1),d3
3386
        bpl     1b
3387
#endif
3388
        movel   IMM (0),d1
3389
        bra     3f
3390
2:      movel   IMM (0),d1
3391
#ifndef __mcoldfire__
3392
        subw    IMM (FLT_MANT_DIG),d3
3393
        addw    IMM (31),d3
3394
#else
3395
        subl    IMM (FLT_MANT_DIG),d3
3396
        addl    IMM (31),d3
3397
#endif
3398
        bset    d3,d1
3399
3:
3400
        movel   d6,d0           | put the ratio in d0-d1
3401
        movel   a0,d7           | get sign back
3402
 
3403
| Because of the normalization we did before we are guaranteed that
3404
| d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set,
3405
| bit 25 could be set, and if it is not set then bit 24 is necessarily set.
3406
        btst    IMM (FLT_MANT_DIG+1),d0
3407
        beq     1f              | if it is not set, then bit 24 is set
3408
        lsrl    IMM (1),d0      |
3409
#ifndef __mcoldfire__
3410
        addw    IMM (1),d2      |
3411
#else
3412
        addl    IMM (1),d2      |
3413
#endif
3414
1:
3415
| Now round, check for over- and underflow, and exit.
3416
        moveq   IMM (DIVIDE),d5
3417
        bra     Lround$exit
3418
 
3419
Ldivsf$inop:
3420
        moveq   IMM (DIVIDE),d5
3421
        bra     Lf$inop
3422
 
3423
Ldivsf$overflow:
3424
        moveq   IMM (DIVIDE),d5
3425
        bra     Lf$overflow
3426
 
3427
Ldivsf$underflow:
3428
        moveq   IMM (DIVIDE),d5
3429
        bra     Lf$underflow
3430
 
3431
Ldivsf$a$0:
3432
        moveq   IMM (DIVIDE),d5
3433
| If a is zero check to see whether b is zero also. In that case return
3434
| NaN; then check if b is NaN, and return NaN also in that case. Else
3435
| return a properly signed zero.
3436
        andl    IMM (0x7fffffff),d1     | clear sign bit and test b
3437
        beq     Lf$inop                 | if b is also zero return NaN
3438
        cmpl    IMM (INFINITY),d1       | check for NaN
3439
        bhi     Lf$inop                 |
3440
        movel   d7,d0                   | else return signed zero
3441
        PICLEA  SYM (_fpCCR),a0         |
3442
        movew   IMM (0),a0@             |
3443
#ifndef __mcoldfire__
3444
        moveml  sp@+,d2-d7              |
3445
#else
3446
        moveml  sp@,d2-d7               |
3447
        | XXX if frame pointer is ever removed, stack pointer must
3448
        | be adjusted here.
3449
#endif
3450
        unlk    a6                      |
3451
        rts                             |
3452
 
3453
Ldivsf$b$0:
3454
        moveq   IMM (DIVIDE),d5
3455
| If we got here a is not zero. Check if a is NaN; in that case return NaN,
3456
| else return +/-INFINITY. Remember that a is in d0 with the sign bit
3457
| cleared already.
3458
        cmpl    IMM (INFINITY),d0       | compare d0 with INFINITY
3459
        bhi     Lf$inop                 | if larger it is NaN
3460
        bra     Lf$div$0                | else signal DIVIDE_BY_ZERO
3461
 
3462
Ldivsf$inf:
3463
        moveq   IMM (DIVIDE),d5
3464
| If a is INFINITY we have to check b
3465
        cmpl    IMM (INFINITY),d1       | compare b with INFINITY
3466
        bge     Lf$inop                 | if b is NaN or INFINITY return NaN
3467
        bra     Lf$overflow             | else return overflow
3468
 
3469
| If a number is denormalized we put an exponent of 1 but do not put the
3470
| bit back into the fraction.
3471
Ldivsf$a$den:
3472
        movel   IMM (1),d2
3473
        andl    d5,d0
3474
1:      addl    d0,d0           | shift a left until bit FLT_MANT_DIG-1 is set
3475
#ifndef __mcoldfire__
3476
        subw    IMM (1),d2      | and adjust exponent
3477
#else
3478
        subl    IMM (1),d2      | and adjust exponent
3479
#endif
3480
        btst    IMM (FLT_MANT_DIG-1),d0
3481
        bne     Ldivsf$1
3482
        bra     1b
3483
 
3484
Ldivsf$b$den:
3485
        movel   IMM (1),d3
3486
        andl    d5,d1
3487
1:      addl    d1,d1           | shift b left until bit FLT_MANT_DIG is set
3488
#ifndef __mcoldfire__
3489
        subw    IMM (1),d3      | and adjust exponent
3490
#else
3491
        subl    IMM (1),d3      | and adjust exponent
3492
#endif
3493
        btst    IMM (FLT_MANT_DIG-1),d1
3494
        bne     Ldivsf$2
3495
        bra     1b
3496
 
3497
Lround$exit:
3498
| This is a common exit point for __mulsf3 and __divsf3.
3499
 
3500
| First check for underlow in the exponent:
3501
#ifndef __mcoldfire__
3502
        cmpw    IMM (-FLT_MANT_DIG-1),d2
3503
#else
3504
        cmpl    IMM (-FLT_MANT_DIG-1),d2
3505
#endif
3506
        blt     Lf$underflow
3507
| It could happen that the exponent is less than 1, in which case the
3508
| number is denormalized. In this case we shift right and adjust the
3509
| exponent until it becomes 1 or the fraction is zero (in the latter case
3510
| we signal underflow and return zero).
3511
        movel   IMM (0),d6      | d6 is used temporarily
3512
#ifndef __mcoldfire__
3513
        cmpw    IMM (1),d2      | if the exponent is less than 1 we
3514
#else
3515
        cmpl    IMM (1),d2      | if the exponent is less than 1 we
3516
#endif
3517
        bge     2f              | have to shift right (denormalize)
3518
1:
3519
#ifndef __mcoldfire__
3520
        addw    IMM (1),d2      | adjust the exponent
3521
        lsrl    IMM (1),d0      | shift right once
3522
        roxrl   IMM (1),d1      |
3523
        roxrl   IMM (1),d6      | d6 collect bits we would lose otherwise
3524
        cmpw    IMM (1),d2      | is the exponent 1 already?
3525
#else
3526
        addql   IMM (1),d2      | adjust the exponent
3527
        lsrl    IMM (1),d6
3528
        btst    IMM (0),d1
3529
        beq     11f
3530
        bset    IMM (31),d6
3531
11:     lsrl    IMM (1),d1
3532
        btst    IMM (0),d0
3533
        beq     10f
3534
        bset    IMM (31),d1
3535
10:     lsrl    IMM (1),d0
3536
        cmpl    IMM (1),d2      | is the exponent 1 already?
3537
#endif
3538
        beq     2f              | if not loop back
3539
        bra     1b              |
3540
        bra     Lf$underflow    | safety check, shouldn't execute '
3541
2:      orl     d6,d1           | this is a trick so we don't lose  '
3542
                                | the extra bits which were flushed right
3543
| Now call the rounding routine (which takes care of denormalized numbers):
3544
        lea     pc@(Lround$0),a0 | to return from rounding routine
3545
        PICLEA  SYM (_fpCCR),a1 | check the rounding mode
3546
#ifdef __mcoldfire__
3547
        clrl    d6
3548
#endif
3549
        movew   a1@(6),d6       | rounding mode in d6
3550
        beq     Lround$to$nearest
3551
#ifndef __mcoldfire__
3552
        cmpw    IMM (ROUND_TO_PLUS),d6
3553
#else
3554
        cmpl    IMM (ROUND_TO_PLUS),d6
3555
#endif
3556
        bhi     Lround$to$minus
3557
        blt     Lround$to$zero
3558
        bra     Lround$to$plus
3559
Lround$0:
3560
| Here we have a correctly rounded result (either normalized or denormalized).
3561
 
3562
| Here we should have either a normalized number or a denormalized one, and
3563
| the exponent is necessarily larger or equal to 1 (so we don't have to  '
3564
| check again for underflow!). We have to check for overflow or for a
3565
| denormalized number (which also signals underflow).
3566
| Check for overflow (i.e., exponent >= 255).
3567
#ifndef __mcoldfire__
3568
        cmpw    IMM (0x00ff),d2
3569
#else
3570
        cmpl    IMM (0x00ff),d2
3571
#endif
3572
        bge     Lf$overflow
3573
| Now check for a denormalized number (exponent==0).
3574
        movew   d2,d2
3575
        beq     Lf$den
3576
1:
3577
| Put back the exponents and sign and return.
3578
#ifndef __mcoldfire__
3579
        lslw    IMM (7),d2      | exponent back to fourth byte
3580
#else
3581
        lsll    IMM (7),d2      | exponent back to fourth byte
3582
#endif
3583
        bclr    IMM (FLT_MANT_DIG-1),d0
3584
        swap    d0              | and put back exponent
3585
#ifndef __mcoldfire__
3586
        orw     d2,d0           |
3587
#else
3588
        orl     d2,d0
3589
#endif
3590
        swap    d0              |
3591
        orl     d7,d0           | and sign also
3592
 
3593
        PICLEA  SYM (_fpCCR),a0
3594
        movew   IMM (0),a0@
3595
#ifndef __mcoldfire__
3596
        moveml  sp@+,d2-d7
3597
#else
3598
        moveml  sp@,d2-d7
3599
        | XXX if frame pointer is ever removed, stack pointer must
3600
        | be adjusted here.
3601
#endif
3602
        unlk    a6
3603
        rts
3604
 
3605
|=============================================================================
3606
|                             __negsf2
3607
|=============================================================================
3608
 
3609
| This is trivial and could be shorter if we didn't bother checking for NaN '
3610
| and +/-INFINITY.
3611
 
3612
| float __negsf2(float);
3613
SYM (__negsf2):
3614
#ifndef __mcoldfire__
3615
        link    a6,IMM (0)
3616
        moveml  d2-d7,sp@-
3617
#else
3618
        link    a6,IMM (-24)
3619
        moveml  d2-d7,sp@
3620
#endif
3621
        moveq   IMM (NEGATE),d5
3622
        movel   a6@(8),d0       | get number to negate in d0
3623
        bchg    IMM (31),d0     | negate
3624
        movel   d0,d1           | make a positive copy
3625
        bclr    IMM (31),d1     |
3626
        tstl    d1              | check for zero
3627
        beq     2f              | if zero (either sign) return +zero
3628
        cmpl    IMM (INFINITY),d1 | compare to +INFINITY
3629
        blt     1f              |
3630
        bhi     Lf$inop         | if larger (fraction not zero) is NaN
3631
        movel   d0,d7           | else get sign and return INFINITY
3632
        andl    IMM (0x80000000),d7
3633
        bra     Lf$infty
3634
1:      PICLEA  SYM (_fpCCR),a0
3635
        movew   IMM (0),a0@
3636
#ifndef __mcoldfire__
3637
        moveml  sp@+,d2-d7
3638
#else
3639
        moveml  sp@,d2-d7
3640
        | XXX if frame pointer is ever removed, stack pointer must
3641
        | be adjusted here.
3642
#endif
3643
        unlk    a6
3644
        rts
3645
2:      bclr    IMM (31),d0
3646
        bra     1b
3647
 
3648
|=============================================================================
3649
|                             __cmpsf2
3650
|=============================================================================
3651
 
3652
GREATER =  1
3653
LESS    = -1
3654
EQUAL   =  0
3655
 
3656
| int __cmpsf2_internal(float, float, int);
3657
SYM (__cmpsf2_internal):
3658
#ifndef __mcoldfire__
3659
        link    a6,IMM (0)
3660
        moveml  d2-d7,sp@-      | save registers
3661
#else
3662
        link    a6,IMM (-24)
3663
        moveml  d2-d7,sp@
3664
#endif
3665
        moveq   IMM (COMPARE),d5
3666
        movel   a6@(8),d0       | get first operand
3667
        movel   a6@(12),d1      | get second operand
3668
| Check if either is NaN, and in that case return garbage and signal
3669
| INVALID_OPERATION. Check also if either is zero, and clear the signs
3670
| if necessary.
3671
        movel   d0,d6
3672
        andl    IMM (0x7fffffff),d0
3673
        beq     Lcmpsf$a$0
3674
        cmpl    IMM (0x7f800000),d0
3675
        bhi     Lcmpf$inop
3676
Lcmpsf$1:
3677
        movel   d1,d7
3678
        andl    IMM (0x7fffffff),d1
3679
        beq     Lcmpsf$b$0
3680
        cmpl    IMM (0x7f800000),d1
3681
        bhi     Lcmpf$inop
3682
Lcmpsf$2:
3683
| Check the signs
3684
        eorl    d6,d7
3685
        bpl     1f
3686
| If the signs are not equal check if a >= 0
3687
        tstl    d6
3688
        bpl     Lcmpsf$a$gt$b   | if (a >= 0 && b < 0) => a > b
3689
        bmi     Lcmpsf$b$gt$a   | if (a < 0 && b >= 0) => a < b
3690
1:
3691
| If the signs are equal check for < 0
3692
        tstl    d6
3693
        bpl     1f
3694
| If both are negative exchange them
3695
#ifndef __mcoldfire__
3696
        exg     d0,d1
3697
#else
3698
        movel   d0,d7
3699
        movel   d1,d0
3700
        movel   d7,d1
3701
#endif
3702
1:
3703
| Now that they are positive we just compare them as longs (does this also
3704
| work for denormalized numbers?).
3705
        cmpl    d0,d1
3706
        bhi     Lcmpsf$b$gt$a   | |b| > |a|
3707
        bne     Lcmpsf$a$gt$b   | |b| < |a|
3708
| If we got here a == b.
3709
        movel   IMM (EQUAL),d0
3710
#ifndef __mcoldfire__
3711
        moveml  sp@+,d2-d7      | put back the registers
3712
#else
3713
        moveml  sp@,d2-d7
3714
#endif
3715
        unlk    a6
3716
        rts
3717
Lcmpsf$a$gt$b:
3718
        movel   IMM (GREATER),d0
3719
#ifndef __mcoldfire__
3720
        moveml  sp@+,d2-d7      | put back the registers
3721
#else
3722
        moveml  sp@,d2-d7
3723
        | XXX if frame pointer is ever removed, stack pointer must
3724
        | be adjusted here.
3725
#endif
3726
        unlk    a6
3727
        rts
3728
Lcmpsf$b$gt$a:
3729
        movel   IMM (LESS),d0
3730
#ifndef __mcoldfire__
3731
        moveml  sp@+,d2-d7      | put back the registers
3732
#else
3733
        moveml  sp@,d2-d7
3734
        | XXX if frame pointer is ever removed, stack pointer must
3735
        | be adjusted here.
3736
#endif
3737
        unlk    a6
3738
        rts
3739
 
3740
Lcmpsf$a$0:
3741
        bclr    IMM (31),d6
3742
        bra     Lcmpsf$1
3743
Lcmpsf$b$0:
3744
        bclr    IMM (31),d7
3745
        bra     Lcmpsf$2
3746
 
3747
Lcmpf$inop:
3748
        movl    a6@(16),d0
3749
        moveq   IMM (INEXACT_RESULT+INVALID_OPERATION),d7
3750
        moveq   IMM (SINGLE_FLOAT),d6
3751
        PICJUMP $_exception_handler
3752
 
3753
| int __cmpsf2(float, float);
3754
SYM (__cmpsf2):
3755
        link    a6,IMM (0)
3756
        pea     1
3757
        movl    a6@(12),sp@-
3758
        movl    a6@(8),sp@-
3759
        bsr (__cmpsf2_internal)
3760
        unlk    a6
3761
        rts
3762
 
3763
|=============================================================================
3764
|                           rounding routines
3765
|=============================================================================
3766
 
3767
| The rounding routines expect the number to be normalized in registers
3768
| d0-d1, with the exponent in register d2. They assume that the
3769
| exponent is larger or equal to 1. They return a properly normalized number
3770
| if possible, and a denormalized number otherwise. The exponent is returned
3771
| in d2.
3772
 
3773
Lround$to$nearest:
3774
| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
3775
| Here we assume that the exponent is not too small (this should be checked
3776
| before entering the rounding routine), but the number could be denormalized.
3777
 
3778
| Check for denormalized numbers:
3779
1:      btst    IMM (FLT_MANT_DIG),d0
3780
        bne     2f              | if set the number is normalized
3781
| Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent
3782
| is one (remember that a denormalized number corresponds to an
3783
| exponent of -F_BIAS+1).
3784
#ifndef __mcoldfire__
3785
        cmpw    IMM (1),d2      | remember that the exponent is at least one
3786
#else
3787
        cmpl    IMM (1),d2      | remember that the exponent is at least one
3788
#endif
3789
        beq     2f              | an exponent of one means denormalized
3790
        addl    d1,d1           | else shift and adjust the exponent
3791
        addxl   d0,d0           |
3792
#ifndef __mcoldfire__
3793
        dbra    d2,1b           |
3794
#else
3795
        subql   IMM (1),d2
3796
        bpl     1b
3797
#endif
3798
2:
3799
| Now round: we do it as follows: after the shifting we can write the
3800
| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
3801
| If delta < 1, do nothing. If delta > 1, add 1 to f.
3802
| If delta == 1, we make sure the rounded number will be even (odd?)
3803
| (after shifting).
3804
        btst    IMM (0),d0      | is delta < 1?
3805
        beq     2f              | if so, do not do anything
3806
        tstl    d1              | is delta == 1?
3807
        bne     1f              | if so round to even
3808
        movel   d0,d1           |
3809
        andl    IMM (2),d1      | bit 1 is the last significant bit
3810
        addl    d1,d0           |
3811
        bra     2f              |
3812
1:      movel   IMM (1),d1      | else add 1
3813
        addl    d1,d0           |
3814
| Shift right once (because we used bit #FLT_MANT_DIG!).
3815
2:      lsrl    IMM (1),d0
3816
| Now check again bit #FLT_MANT_DIG (rounding could have produced a
3817
| 'fraction overflow' ...).
3818
        btst    IMM (FLT_MANT_DIG),d0
3819
        beq     1f
3820
        lsrl    IMM (1),d0
3821
#ifndef __mcoldfire__
3822
        addw    IMM (1),d2
3823
#else
3824
        addql   IMM (1),d2
3825
#endif
3826
1:
3827
| If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we
3828
| have to put the exponent to zero and return a denormalized number.
3829
        btst    IMM (FLT_MANT_DIG-1),d0
3830
        beq     1f
3831
        jmp     a0@
3832
1:      movel   IMM (0),d2
3833
        jmp     a0@
3834
 
3835
Lround$to$zero:
3836
Lround$to$plus:
3837
Lround$to$minus:
3838
        jmp     a0@
3839
#endif /* L_float */
3840
 
3841
| gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2,
3842
| __ledf2, __ltdf2 to all return the same value as a direct call to
3843
| __cmpdf2 would.  In this implementation, each of these routines
3844
| simply calls __cmpdf2.  It would be more efficient to give the
3845
| __cmpdf2 routine several names, but separating them out will make it
3846
| easier to write efficient versions of these routines someday.
3847
| If the operands recompare unordered unordered __gtdf2 and __gedf2 return -1.
3848
| The other routines return 1.
3849
 
3850
#ifdef  L_eqdf2
3851
        .text
3852
        .proc
3853
        .globl  SYM (__eqdf2)
3854
SYM (__eqdf2):
3855
        link    a6,IMM (0)
3856
        pea     1
3857
        movl    a6@(20),sp@-
3858
        movl    a6@(16),sp@-
3859
        movl    a6@(12),sp@-
3860
        movl    a6@(8),sp@-
3861
        PICCALL SYM (__cmpdf2_internal)
3862
        unlk    a6
3863
        rts
3864
#endif /* L_eqdf2 */
3865
 
3866
#ifdef  L_nedf2
3867
        .text
3868
        .proc
3869
        .globl  SYM (__nedf2)
3870
SYM (__nedf2):
3871
        link    a6,IMM (0)
3872
        pea     1
3873
        movl    a6@(20),sp@-
3874
        movl    a6@(16),sp@-
3875
        movl    a6@(12),sp@-
3876
        movl    a6@(8),sp@-
3877
        PICCALL SYM (__cmpdf2_internal)
3878
        unlk    a6
3879
        rts
3880
#endif /* L_nedf2 */
3881
 
3882
#ifdef  L_gtdf2
3883
        .text
3884
        .proc
3885
        .globl  SYM (__gtdf2)
3886
SYM (__gtdf2):
3887
        link    a6,IMM (0)
3888
        pea     -1
3889
        movl    a6@(20),sp@-
3890
        movl    a6@(16),sp@-
3891
        movl    a6@(12),sp@-
3892
        movl    a6@(8),sp@-
3893
        PICCALL SYM (__cmpdf2_internal)
3894
        unlk    a6
3895
        rts
3896
#endif /* L_gtdf2 */
3897
 
3898
#ifdef  L_gedf2
3899
        .text
3900
        .proc
3901
        .globl  SYM (__gedf2)
3902
SYM (__gedf2):
3903
        link    a6,IMM (0)
3904
        pea     -1
3905
        movl    a6@(20),sp@-
3906
        movl    a6@(16),sp@-
3907
        movl    a6@(12),sp@-
3908
        movl    a6@(8),sp@-
3909
        PICCALL SYM (__cmpdf2_internal)
3910
        unlk    a6
3911
        rts
3912
#endif /* L_gedf2 */
3913
 
3914
#ifdef  L_ltdf2
3915
        .text
3916
        .proc
3917
        .globl  SYM (__ltdf2)
3918
SYM (__ltdf2):
3919
        link    a6,IMM (0)
3920
        pea     1
3921
        movl    a6@(20),sp@-
3922
        movl    a6@(16),sp@-
3923
        movl    a6@(12),sp@-
3924
        movl    a6@(8),sp@-
3925
        PICCALL SYM (__cmpdf2_internal)
3926
        unlk    a6
3927
        rts
3928
#endif /* L_ltdf2 */
3929
 
3930
#ifdef  L_ledf2
3931
        .text
3932
        .proc
3933
        .globl  SYM (__ledf2)
3934
SYM (__ledf2):
3935
        link    a6,IMM (0)
3936
        pea     1
3937
        movl    a6@(20),sp@-
3938
        movl    a6@(16),sp@-
3939
        movl    a6@(12),sp@-
3940
        movl    a6@(8),sp@-
3941
        PICCALL SYM (__cmpdf2_internal)
3942
        unlk    a6
3943
        rts
3944
#endif /* L_ledf2 */
3945
 
3946
| The comments above about __eqdf2, et. al., also apply to __eqsf2,
3947
| et. al., except that the latter call __cmpsf2 rather than __cmpdf2.
3948
 
3949
#ifdef  L_eqsf2
3950
        .text
3951
        .proc
3952
        .globl  SYM (__eqsf2)
3953
SYM (__eqsf2):
3954
        link    a6,IMM (0)
3955
        pea     1
3956
        movl    a6@(12),sp@-
3957
        movl    a6@(8),sp@-
3958
        PICCALL SYM (__cmpsf2_internal)
3959
        unlk    a6
3960
        rts
3961
#endif /* L_eqsf2 */
3962
 
3963
#ifdef  L_nesf2
3964
        .text
3965
        .proc
3966
        .globl  SYM (__nesf2)
3967
SYM (__nesf2):
3968
        link    a6,IMM (0)
3969
        pea     1
3970
        movl    a6@(12),sp@-
3971
        movl    a6@(8),sp@-
3972
        PICCALL SYM (__cmpsf2_internal)
3973
        unlk    a6
3974
        rts
3975
#endif /* L_nesf2 */
3976
 
3977
#ifdef  L_gtsf2
3978
        .text
3979
        .proc
3980
        .globl  SYM (__gtsf2)
3981
SYM (__gtsf2):
3982
        link    a6,IMM (0)
3983
        pea     -1
3984
        movl    a6@(12),sp@-
3985
        movl    a6@(8),sp@-
3986
        PICCALL SYM (__cmpsf2_internal)
3987
        unlk    a6
3988
        rts
3989
#endif /* L_gtsf2 */
3990
 
3991
#ifdef  L_gesf2
3992
        .text
3993
        .proc
3994
        .globl  SYM (__gesf2)
3995
SYM (__gesf2):
3996
        link    a6,IMM (0)
3997
        pea     -1
3998
        movl    a6@(12),sp@-
3999
        movl    a6@(8),sp@-
4000
        PICCALL SYM (__cmpsf2_internal)
4001
        unlk    a6
4002
        rts
4003
#endif /* L_gesf2 */
4004
 
4005
#ifdef  L_ltsf2
4006
        .text
4007
        .proc
4008
        .globl  SYM (__ltsf2)
4009
SYM (__ltsf2):
4010
        link    a6,IMM (0)
4011
        pea     1
4012
        movl    a6@(12),sp@-
4013
        movl    a6@(8),sp@-
4014
        PICCALL SYM (__cmpsf2_internal)
4015
        unlk    a6
4016
        rts
4017
#endif /* L_ltsf2 */
4018
 
4019
#ifdef  L_lesf2
4020
        .text
4021
        .proc
4022
        .globl  SYM (__lesf2)
4023
SYM (__lesf2):
4024
        link    a6,IMM (0)
4025
        pea     1
4026
        movl    a6@(12),sp@-
4027
        movl    a6@(8),sp@-
4028
        PICCALL SYM (__cmpsf2_internal)
4029
        unlk    a6
4030
        rts
4031
#endif /* L_lesf2 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.