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