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