OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [m68k/] [lb1sf68.asm] - Blame information for rev 300

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

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

powered by: WebSVN 2.1.0

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