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