diff options
Diffstat (limited to 'gcc/config/m68k')
-rw-r--r-- | gcc/config/m68k/crti.s | 44 | ||||
-rw-r--r-- | gcc/config/m68k/crtn.s | 40 | ||||
-rw-r--r-- | gcc/config/m68k/fpgnulib.c | 595 | ||||
-rw-r--r-- | gcc/config/m68k/lb1sf68.asm | 4116 | ||||
-rw-r--r-- | gcc/config/m68k/t-crtstuff | 10 | ||||
-rw-r--r-- | gcc/config/m68k/t-floatlib | 31 | ||||
-rw-r--r-- | gcc/config/m68k/t-linux | 4 | ||||
-rw-r--r-- | gcc/config/m68k/t-m68kelf | 4 | ||||
-rw-r--r-- | gcc/config/m68k/t-mlibs | 3 | ||||
-rw-r--r-- | gcc/config/m68k/t-slibgcc-elf-ver | 3 | ||||
-rw-r--r-- | gcc/config/m68k/t-uclinux | 5 |
11 files changed, 2 insertions, 4853 deletions
diff --git a/gcc/config/m68k/crti.s b/gcc/config/m68k/crti.s deleted file mode 100644 index 12fb59f4130..00000000000 --- a/gcc/config/m68k/crti.s +++ /dev/null @@ -1,44 +0,0 @@ -/* Specialized code needed to support construction and destruction of - file-scope objects in C++ and Java code, and to support exception handling. - Copyright (C) 1999, 2008, 2009 Free Software Foundation, Inc. - Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -/* - * This file just supplies function prologues for the .init and .fini - * sections. It is linked in before crtbegin.o. - */ - - .ident "GNU C crti.o" - - .section .init - .globl _init - .type _init,@function -_init: - linkw %fp,#0 - - .section .fini - .globl _fini - .type _fini,@function -_fini: - linkw %fp,#0 diff --git a/gcc/config/m68k/crtn.s b/gcc/config/m68k/crtn.s deleted file mode 100644 index b7d70f02ed5..00000000000 --- a/gcc/config/m68k/crtn.s +++ /dev/null @@ -1,40 +0,0 @@ -/* Specialized code needed to support construction and destruction of - file-scope objects in C++ and Java code, and to support exception handling. - Copyright (C) 1999, 2008, 2009 Free Software Foundation, Inc. - Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -/* - * This file supplies function epilogues for the .init and .fini sections. - * It is linked in after all other files. - */ - - .ident "GNU C crtn.o" - - .section .init - unlk %fp - rts - - .section .fini - unlk %fp - rts diff --git a/gcc/config/m68k/fpgnulib.c b/gcc/config/m68k/fpgnulib.c deleted file mode 100644 index 2a7f6c75d11..00000000000 --- a/gcc/config/m68k/fpgnulib.c +++ /dev/null @@ -1,595 +0,0 @@ -/* This is a stripped down version of floatlib.c. It supplies only those - functions which exist in libgcc, but for which there is not assembly - language versions in m68k/lb1sf68.asm. - - It also includes simplistic support for extended floats (by working in - double precision). You must compile this file again with -DEXTFLOAT - to get this support. */ - -/* -** gnulib support for software floating point. -** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. -** Permission is granted to do *anything* you want with this file, -** commercial or otherwise, provided this message remains intact. So there! -** I would appreciate receiving any updates/patches/changes that anyone -** makes, and am willing to be the repository for said changes (am I -** making a big mistake?). -** -** Pat Wood -** Pipeline Associates, Inc. -** pipeline!phw@motown.com or -** sun!pipeline!phw or -** uunet!motown!pipeline!phw -** -** 05/01/91 -- V1.0 -- first release to gcc mailing lists -** 05/04/91 -- V1.1 -- added float and double prototypes and return values -** -- fixed problems with adding and subtracting zero -** -- fixed rounding in truncdfsf2 -** -- fixed SWAP define and tested on 386 -*/ - -/* -** The following are routines that replace the gnulib soft floating point -** routines that are called automatically when -msoft-float is selected. -** The support single and double precision IEEE format, with provisions -** for byte-swapped machines (tested on 386). Some of the double-precision -** routines work at full precision, but most of the hard ones simply punt -** and call the single precision routines, producing a loss of accuracy. -** long long support is not assumed or included. -** Overall accuracy is close to IEEE (actually 68882) for single-precision -** arithmetic. I think there may still be a 1 in 1000 chance of a bit -** being rounded the wrong way during a multiply. I'm not fussy enough to -** bother with it, but if anyone is, knock yourself out. -** -** Efficiency has only been addressed where it was obvious that something -** would make a big difference. Anyone who wants to do this right for -** best speed should go in and rewrite in assembler. -** -** I have tested this only on a 68030 workstation and 386/ix integrated -** in with -msoft-float. -*/ - -/* the following deal with IEEE single-precision numbers */ -#define EXCESS 126L -#define SIGNBIT 0x80000000L -#define HIDDEN (1L << 23L) -#define SIGN(fp) ((fp) & SIGNBIT) -#define EXP(fp) (((fp) >> 23L) & 0xFF) -#define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN) -#define PACK(s,e,m) ((s) | ((e) << 23L) | (m)) - -/* the following deal with IEEE double-precision numbers */ -#define EXCESSD 1022L -#define HIDDEND (1L << 20L) -#define EXPDBITS 11 -#define EXPDMASK 0x7FFL -#define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL) -#define SIGND(fp) ((fp.l.upper) & SIGNBIT) -#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ - (fp.l.lower >> 22)) -#define MANTDMASK 0xFFFFFL /* mask of upper part */ - -/* the following deal with IEEE extended-precision numbers */ -#define EXCESSX 16382L -#define HIDDENX (1L << 31L) -#define EXPXBITS 15 -#define EXPXMASK 0x7FFF -#define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK) -#define SIGNX(fp) ((fp.l.upper) & SIGNBIT) -#define MANTXMASK 0x7FFFFFFFL /* mask of upper part */ - -union double_long -{ - double d; - struct { - long upper; - unsigned long lower; - } l; -}; - -union float_long { - float f; - long l; -}; - -union long_double_long -{ - long double ld; - struct - { - long upper; - unsigned long middle; - unsigned long lower; - } l; -}; - -#ifndef EXTFLOAT - -int -__unordsf2(float a, float b) -{ - union float_long fl; - - fl.f = a; - if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0) - return 1; - fl.f = b; - if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0) - return 1; - return 0; -} - -int -__unorddf2(double a, double b) -{ - union double_long dl; - - dl.d = a; - if (EXPD(dl) == EXPDMASK - && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0)) - return 1; - dl.d = b; - if (EXPD(dl) == EXPDMASK - && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0)) - return 1; - return 0; -} - -/* convert unsigned int to double */ -double -__floatunsidf (unsigned long a1) -{ - long exp = 32 + EXCESSD; - union double_long dl; - - if (!a1) - { - dl.l.upper = dl.l.lower = 0; - return dl.d; - } - - while (a1 < 0x2000000L) - { - a1 <<= 4; - exp -= 4; - } - - while (a1 < 0x80000000L) - { - a1 <<= 1; - exp--; - } - - /* pack up and go home */ - dl.l.upper = exp << 20L; - dl.l.upper |= (a1 >> 11L) & ~HIDDEND; - dl.l.lower = a1 << 21L; - - return dl.d; -} - -/* convert int to double */ -double -__floatsidf (long a1) -{ - long sign = 0, exp = 31 + EXCESSD; - union double_long dl; - - if (!a1) - { - dl.l.upper = dl.l.lower = 0; - return dl.d; - } - - if (a1 < 0) - { - sign = SIGNBIT; - a1 = (long)-(unsigned long)a1; - if (a1 < 0) - { - dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L); - dl.l.lower = 0; - return dl.d; - } - } - - while (a1 < 0x1000000L) - { - a1 <<= 4; - exp -= 4; - } - - while (a1 < 0x40000000L) - { - a1 <<= 1; - exp--; - } - - /* pack up and go home */ - dl.l.upper = sign; - dl.l.upper |= exp << 20L; - dl.l.upper |= (a1 >> 10L) & ~HIDDEND; - dl.l.lower = a1 << 22L; - - return dl.d; -} - -/* convert unsigned int to float */ -float -__floatunsisf (unsigned long l) -{ - double foo = __floatunsidf (l); - return foo; -} - -/* convert int to float */ -float -__floatsisf (long l) -{ - double foo = __floatsidf (l); - return foo; -} - -/* convert float to double */ -double -__extendsfdf2 (float a1) -{ - register union float_long fl1; - register union double_long dl; - register long exp; - register long mant; - - fl1.f = a1; - - dl.l.upper = SIGN (fl1.l); - if ((fl1.l & ~SIGNBIT) == 0) - { - dl.l.lower = 0; - return dl.d; - } - - exp = EXP(fl1.l); - mant = MANT (fl1.l) & ~HIDDEN; - if (exp == 0) - { - /* Denormal. */ - exp = 1; - while (!(mant & HIDDEN)) - { - mant <<= 1; - exp--; - } - mant &= ~HIDDEN; - } - exp = exp - EXCESS + EXCESSD; - dl.l.upper |= exp << 20; - dl.l.upper |= mant >> 3; - dl.l.lower = mant << 29; - - return dl.d; -} - -/* convert double to float */ -float -__truncdfsf2 (double a1) -{ - register long exp; - register long mant; - register union float_long fl; - register union double_long dl1; - int sticky; - int shift; - - dl1.d = a1; - - if ((dl1.l.upper & ~SIGNBIT) == 0 && !dl1.l.lower) - { - fl.l = SIGND(dl1); - return fl.f; - } - - exp = EXPD (dl1) - EXCESSD + EXCESS; - - sticky = dl1.l.lower & ((1 << 22) - 1); - mant = MANTD (dl1); - /* shift double mantissa 6 bits so we can round */ - sticky |= mant & ((1 << 6) - 1); - mant >>= 6; - - /* Check for underflow and denormals. */ - if (exp <= 0) - { - if (exp < -24) - { - sticky |= mant; - mant = 0; - } - else - { - sticky |= mant & ((1 << (1 - exp)) - 1); - mant >>= 1 - exp; - } - exp = 0; - } - - /* now round */ - shift = 1; - if ((mant & 1) && (sticky || (mant & 2))) - { - int rounding = exp ? 2 : 1; - - mant += 1; - - /* did the round overflow? */ - if (mant >= (HIDDEN << rounding)) - { - exp++; - shift = rounding; - } - } - /* shift down */ - mant >>= shift; - - mant &= ~HIDDEN; - - /* pack up and go home */ - fl.l = PACK (SIGND (dl1), exp, mant); - return (fl.f); -} - -/* convert double to int */ -long -__fixdfsi (double a1) -{ - register union double_long dl1; - register long exp; - register long l; - - dl1.d = a1; - - if (!dl1.l.upper && !dl1.l.lower) - return 0; - - exp = EXPD (dl1) - EXCESSD - 31; - l = MANTD (dl1); - - if (exp > 0) - { - /* Return largest integer. */ - return SIGND (dl1) ? 0x80000000L : 0x7fffffffL; - } - - if (exp <= -32) - return 0; - - /* shift down until exp = 0 */ - if (exp < 0) - l >>= -exp; - - return (SIGND (dl1) ? -l : l); -} - -/* convert float to int */ -long -__fixsfsi (float a1) -{ - double foo = a1; - return __fixdfsi (foo); -} - -#else /* EXTFLOAT */ - -/* We do not need these routines for coldfire, as it has no extended - float format. */ -#if !defined (__mcoldfire__) - -/* Primitive extended precision floating point support. - - We assume all numbers are normalized, don't do any rounding, etc. */ - -/* Prototypes for the above in case we use them. */ -double __floatunsidf (unsigned long); -double __floatsidf (long); -float __floatsisf (long); -double __extendsfdf2 (float); -float __truncdfsf2 (double); -long __fixdfsi (double); -long __fixsfsi (float); - -int -__unordxf2(long double a, long double b) -{ - union long_double_long ldl; - - ldl.ld = a; - if (EXPX(ldl) == EXPXMASK - && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0)) - return 1; - ldl.ld = b; - if (EXPX(ldl) == EXPXMASK - && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0)) - return 1; - return 0; -} - -/* convert double to long double */ -long double -__extenddfxf2 (double d) -{ - register union double_long dl; - register union long_double_long ldl; - register long exp; - - dl.d = d; - /*printf ("dfxf in: %g\n", d);*/ - - ldl.l.upper = SIGND (dl); - if ((dl.l.upper & ~SIGNBIT) == 0 && !dl.l.lower) - { - ldl.l.middle = 0; - ldl.l.lower = 0; - return ldl.ld; - } - - exp = EXPD (dl) - EXCESSD + EXCESSX; - ldl.l.upper |= exp << 16; - ldl.l.middle = HIDDENX; - /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */ - ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20); - /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */ - ldl.l.middle |= dl.l.lower >> (1 + 20); - /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */ - ldl.l.lower = dl.l.lower << (32 - 21); - - /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/ - return ldl.ld; -} - -/* convert long double to double */ -double -__truncxfdf2 (long double ld) -{ - register long exp; - register union double_long dl; - register union long_double_long ldl; - - ldl.ld = ld; - /*printf ("xfdf in: %s\n", dumpxf (ld));*/ - - dl.l.upper = SIGNX (ldl); - if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower) - { - dl.l.lower = 0; - return dl.d; - } - - exp = EXPX (ldl) - EXCESSX + EXCESSD; - /* ??? quick and dirty: keep `exp' sane */ - if (exp >= EXPDMASK) - exp = EXPDMASK - 1; - dl.l.upper |= exp << (32 - (EXPDBITS + 1)); - /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */ - dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1); - dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1)); - dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1); - - /*printf ("xfdf out: %g\n", dl.d);*/ - return dl.d; -} - -/* convert a float to a long double */ -long double -__extendsfxf2 (float f) -{ - long double foo = __extenddfxf2 (__extendsfdf2 (f)); - return foo; -} - -/* convert a long double to a float */ -float -__truncxfsf2 (long double ld) -{ - float foo = __truncdfsf2 (__truncxfdf2 (ld)); - return foo; -} - -/* convert an int to a long double */ -long double -__floatsixf (long l) -{ - double foo = __floatsidf (l); - return foo; -} - -/* convert an unsigned int to a long double */ -long double -__floatunsixf (unsigned long l) -{ - double foo = __floatunsidf (l); - return foo; -} - -/* convert a long double to an int */ -long -__fixxfsi (long double ld) -{ - long foo = __fixdfsi ((double) ld); - return foo; -} - -/* The remaining provide crude math support by working in double precision. */ - -long double -__addxf3 (long double x1, long double x2) -{ - return (double) x1 + (double) x2; -} - -long double -__subxf3 (long double x1, long double x2) -{ - return (double) x1 - (double) x2; -} - -long double -__mulxf3 (long double x1, long double x2) -{ - return (double) x1 * (double) x2; -} - -long double -__divxf3 (long double x1, long double x2) -{ - return (double) x1 / (double) x2; -} - -long double -__negxf2 (long double x1) -{ - return - (double) x1; -} - -long -__cmpxf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -long -__eqxf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -long -__nexf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -long -__ltxf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -long -__lexf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -long -__gtxf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -long -__gexf2 (long double x1, long double x2) -{ - return __cmpdf2 ((double) x1, (double) x2); -} - -#endif /* !__mcoldfire__ */ -#endif /* EXTFLOAT */ diff --git a/gcc/config/m68k/lb1sf68.asm b/gcc/config/m68k/lb1sf68.asm deleted file mode 100644 index 0339a092c4f..00000000000 --- a/gcc/config/m68k/lb1sf68.asm +++ /dev/null @@ -1,4116 +0,0 @@ -/* libgcc routines for 68000 w/o floating-point hardware. - Copyright (C) 1994, 1996, 1997, 1998, 2008, 2009 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This file is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -/* Use this one for any 680x0; assumes no floating point hardware. - The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. - Some of this code comes from MINIX, via the folks at ericsson. - D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 -*/ - -/* These are predefined by new versions of GNU cpp. */ - -#ifndef __USER_LABEL_PREFIX__ -#define __USER_LABEL_PREFIX__ _ -#endif - -#ifndef __REGISTER_PREFIX__ -#define __REGISTER_PREFIX__ -#endif - -#ifndef __IMMEDIATE_PREFIX__ -#define __IMMEDIATE_PREFIX__ # -#endif - -/* ANSI concatenation macros. */ - -#define CONCAT1(a, b) CONCAT2(a, b) -#define CONCAT2(a, b) a ## b - -/* Use the right prefix for global labels. */ - -#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) - -/* Note that X is a function. */ - -#ifdef __ELF__ -#define FUNC(x) .type SYM(x),function -#else -/* The .proc pseudo-op is accepted, but ignored, by GAS. We could just - define this to the empty string for non-ELF systems, but defining it - to .proc means that the information is available to the assembler if - the need arises. */ -#define FUNC(x) .proc -#endif - -/* Use the right prefix for registers. */ - -#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) - -/* Use the right prefix for immediate values. */ - -#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) - -#define d0 REG (d0) -#define d1 REG (d1) -#define d2 REG (d2) -#define d3 REG (d3) -#define d4 REG (d4) -#define d5 REG (d5) -#define d6 REG (d6) -#define d7 REG (d7) -#define a0 REG (a0) -#define a1 REG (a1) -#define a2 REG (a2) -#define a3 REG (a3) -#define a4 REG (a4) -#define a5 REG (a5) -#define a6 REG (a6) -#define fp REG (fp) -#define sp REG (sp) -#define pc REG (pc) - -/* Provide a few macros to allow for PIC code support. - * With PIC, data is stored A5 relative so we've got to take a bit of special - * care to ensure that all loads of global data is via A5. PIC also requires - * jumps and subroutine calls to be PC relative rather than absolute. We cheat - * a little on this and in the PIC case, we use short offset branches and - * hope that the final object code is within range (which it should be). - */ -#ifndef __PIC__ - - /* Non PIC (absolute/relocatable) versions */ - - .macro PICCALL addr - jbsr \addr - .endm - - .macro PICJUMP addr - jmp \addr - .endm - - .macro PICLEA sym, reg - lea \sym, \reg - .endm - - .macro PICPEA sym, areg - pea \sym - .endm - -#else /* __PIC__ */ - -# if defined (__uClinux__) - - /* Versions for uClinux */ - -# if defined(__ID_SHARED_LIBRARY__) - - /* -mid-shared-library versions */ - - .macro PICLEA sym, reg - movel a5@(_current_shared_library_a5_offset_), \reg - movel \sym@GOT(\reg), \reg - .endm - - .macro PICPEA sym, areg - movel a5@(_current_shared_library_a5_offset_), \areg - movel \sym@GOT(\areg), sp@- - .endm - - .macro PICCALL addr - PICLEA \addr,a0 - jsr a0@ - .endm - - .macro PICJUMP addr - PICLEA \addr,a0 - jmp a0@ - .endm - -# else /* !__ID_SHARED_LIBRARY__ */ - - /* Versions for -msep-data */ - - .macro PICLEA sym, reg - movel \sym@GOT(a5), \reg - .endm - - .macro PICPEA sym, areg - movel \sym@GOT(a5), sp@- - .endm - - .macro PICCALL addr -#if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) - lea \addr-.-8,a0 - jsr pc@(a0) -#else - jbsr \addr -#endif - .endm - - .macro PICJUMP addr - /* ISA C has no bra.l instruction, and since this assembly file - gets assembled into multiple object files, we avoid the - bra instruction entirely. */ -#if defined (__mcoldfire__) && !defined (__mcfisab__) - lea \addr-.-8,a0 - jmp pc@(a0) -#else - bra \addr -#endif - .endm - -# endif - -# else /* !__uClinux__ */ - - /* Versions for Linux */ - - .macro PICLEA sym, reg - movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \reg - lea (-6, pc, \reg), \reg - movel \sym@GOT(\reg), \reg - .endm - - .macro PICPEA sym, areg - movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \areg - lea (-6, pc, \areg), \areg - movel \sym@GOT(\areg), sp@- - .endm - - .macro PICCALL addr -#if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) - lea \addr-.-8,a0 - jsr pc@(a0) -#else - jbsr \addr -#endif - .endm - - .macro PICJUMP addr - /* ISA C has no bra.l instruction, and since this assembly file - gets assembled into multiple object files, we avoid the - bra instruction entirely. */ -#if defined (__mcoldfire__) && !defined (__mcfisab__) - lea \addr-.-8,a0 - jmp pc@(a0) -#else - bra \addr -#endif - .endm - -# endif -#endif /* __PIC__ */ - - -#ifdef L_floatex - -| This is an attempt at a decent floating point (single, double and -| extended double) code for the GNU C compiler. It should be easy to -| adapt to other compilers (but beware of the local labels!). - -| Starting date: 21 October, 1990 - -| It is convenient to introduce the notation (s,e,f) for a floating point -| number, where s=sign, e=exponent, f=fraction. We will call a floating -| point number fpn to abbreviate, independently of the precision. -| Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023 -| for doubles and 16383 for long doubles). We then have the following -| different cases: -| 1. Normalized fpns have 0 < e < MAX_EXP. They correspond to -| (-1)^s x 1.f x 2^(e-bias-1). -| 2. Denormalized fpns have e=0. They correspond to numbers of the form -| (-1)^s x 0.f x 2^(-bias). -| 3. +/-INFINITY have e=MAX_EXP, f=0. -| 4. Quiet NaN (Not a Number) have all bits set. -| 5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1. - -|============================================================================= -| exceptions -|============================================================================= - -| This is the floating point condition code register (_fpCCR): -| -| struct { -| short _exception_bits; -| short _trap_enable_bits; -| short _sticky_bits; -| short _rounding_mode; -| short _format; -| short _last_operation; -| union { -| float sf; -| double df; -| } _operand1; -| union { -| float sf; -| double df; -| } _operand2; -| } _fpCCR; - - .data - .even - - .globl SYM (_fpCCR) - -SYM (_fpCCR): -__exception_bits: - .word 0 -__trap_enable_bits: - .word 0 -__sticky_bits: - .word 0 -__rounding_mode: - .word ROUND_TO_NEAREST -__format: - .word NIL -__last_operation: - .word NOOP -__operand1: - .long 0 - .long 0 -__operand2: - .long 0 - .long 0 - -| Offsets: -EBITS = __exception_bits - SYM (_fpCCR) -TRAPE = __trap_enable_bits - SYM (_fpCCR) -STICK = __sticky_bits - SYM (_fpCCR) -ROUND = __rounding_mode - SYM (_fpCCR) -FORMT = __format - SYM (_fpCCR) -LASTO = __last_operation - SYM (_fpCCR) -OPER1 = __operand1 - SYM (_fpCCR) -OPER2 = __operand2 - SYM (_fpCCR) - -| The following exception types are supported: -INEXACT_RESULT = 0x0001 -UNDERFLOW = 0x0002 -OVERFLOW = 0x0004 -DIVIDE_BY_ZERO = 0x0008 -INVALID_OPERATION = 0x0010 - -| The allowed rounding modes are: -UNKNOWN = -1 -ROUND_TO_NEAREST = 0 | round result to nearest representable value -ROUND_TO_ZERO = 1 | round result towards zero -ROUND_TO_PLUS = 2 | round result towards plus infinity -ROUND_TO_MINUS = 3 | round result towards minus infinity - -| The allowed values of format are: -NIL = 0 -SINGLE_FLOAT = 1 -DOUBLE_FLOAT = 2 -LONG_FLOAT = 3 - -| The allowed values for the last operation are: -NOOP = 0 -ADD = 1 -MULTIPLY = 2 -DIVIDE = 3 -NEGATE = 4 -COMPARE = 5 -EXTENDSFDF = 6 -TRUNCDFSF = 7 - -|============================================================================= -| __clear_sticky_bits -|============================================================================= - -| The sticky bits are normally not cleared (thus the name), whereas the -| exception type and exception value reflect the last computation. -| This routine is provided to clear them (you can also write to _fpCCR, -| since it is globally visible). - - .globl SYM (__clear_sticky_bit) - - .text - .even - -| void __clear_sticky_bits(void); -SYM (__clear_sticky_bit): - PICLEA SYM (_fpCCR),a0 -#ifndef __mcoldfire__ - movew IMM (0),a0@(STICK) -#else - clr.w a0@(STICK) -#endif - rts - -|============================================================================= -| $_exception_handler -|============================================================================= - - .globl $_exception_handler - - .text - .even - -| This is the common exit point if an exception occurs. -| NOTE: it is NOT callable from C! -| It expects the exception type in d7, the format (SINGLE_FLOAT, -| DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5. -| It sets the corresponding exception and sticky bits, and the format. -| Depending on the format if fills the corresponding slots for the -| operands which produced the exception (all this information is provided -| so if you write your own exception handlers you have enough information -| to deal with the problem). -| Then checks to see if the corresponding exception is trap-enabled, -| in which case it pushes the address of _fpCCR and traps through -| trap FPTRAP (15 for the moment). - -FPTRAP = 15 - -$_exception_handler: - PICLEA SYM (_fpCCR),a0 - movew d7,a0@(EBITS) | set __exception_bits -#ifndef __mcoldfire__ - orw d7,a0@(STICK) | and __sticky_bits -#else - movew a0@(STICK),d4 - orl d7,d4 - movew d4,a0@(STICK) -#endif - movew d6,a0@(FORMT) | and __format - movew d5,a0@(LASTO) | and __last_operation - -| Now put the operands in place: -#ifndef __mcoldfire__ - cmpw IMM (SINGLE_FLOAT),d6 -#else - cmpl IMM (SINGLE_FLOAT),d6 -#endif - beq 1f - movel a6@(8),a0@(OPER1) - movel a6@(12),a0@(OPER1+4) - movel a6@(16),a0@(OPER2) - movel a6@(20),a0@(OPER2+4) - bra 2f -1: movel a6@(8),a0@(OPER1) - movel a6@(12),a0@(OPER2) -2: -| And check whether the exception is trap-enabled: -#ifndef __mcoldfire__ - andw a0@(TRAPE),d7 | is exception trap-enabled? -#else - clrl d6 - movew a0@(TRAPE),d6 - andl d6,d7 -#endif - beq 1f | no, exit - PICPEA SYM (_fpCCR),a1 | yes, push address of _fpCCR - trap IMM (FPTRAP) | and trap -#ifndef __mcoldfire__ -1: moveml sp@+,d2-d7 | restore data registers -#else -1: moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | and return - rts -#endif /* L_floatex */ - -#ifdef L_mulsi3 - .text - FUNC(__mulsi3) - .globl SYM (__mulsi3) -SYM (__mulsi3): - movew sp@(4), d0 /* x0 -> d0 */ - muluw sp@(10), d0 /* x0*y1 */ - movew sp@(6), d1 /* x1 -> d1 */ - muluw sp@(8), d1 /* x1*y0 */ -#ifndef __mcoldfire__ - addw d1, d0 -#else - addl d1, d0 -#endif - swap d0 - clrw d0 - movew sp@(6), d1 /* x1 -> d1 */ - muluw sp@(10), d1 /* x1*y1 */ - addl d1, d0 - - rts -#endif /* L_mulsi3 */ - -#ifdef L_udivsi3 - .text - FUNC(__udivsi3) - .globl SYM (__udivsi3) -SYM (__udivsi3): -#ifndef __mcoldfire__ - movel d2, sp@- - movel sp@(12), d1 /* d1 = divisor */ - movel sp@(8), d0 /* d0 = dividend */ - - cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */ - jcc L3 /* then try next algorithm */ - movel d0, d2 - clrw d2 - swap d2 - divu d1, d2 /* high quotient in lower word */ - movew d2, d0 /* save high quotient */ - swap d0 - movew sp@(10), d2 /* get low dividend + high rest */ - divu d1, d2 /* low quotient */ - movew d2, d0 - jra L6 - -L3: movel d1, d2 /* use d2 as divisor backup */ -L4: lsrl IMM (1), d1 /* shift divisor */ - lsrl IMM (1), d0 /* shift dividend */ - cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */ - jcc L4 - divu d1, d0 /* now we have 16-bit divisor */ - andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */ - -/* Multiply the 16-bit tentative quotient with the 32-bit divisor. Because of - the operand ranges, this might give a 33-bit product. If this product is - greater than the dividend, the tentative quotient was too large. */ - movel d2, d1 - mulu d0, d1 /* low part, 32 bits */ - swap d2 - mulu d0, d2 /* high part, at most 17 bits */ - swap d2 /* align high part with low part */ - tstw d2 /* high part 17 bits? */ - jne L5 /* if 17 bits, quotient was too large */ - addl d2, d1 /* add parts */ - jcs L5 /* if sum is 33 bits, quotient was too large */ - cmpl sp@(8), d1 /* compare the sum with the dividend */ - jls L6 /* if sum > dividend, quotient was too large */ -L5: subql IMM (1), d0 /* adjust quotient */ - -L6: movel sp@+, d2 - rts - -#else /* __mcoldfire__ */ - -/* ColdFire implementation of non-restoring division algorithm from - Hennessy & Patterson, Appendix A. */ - link a6,IMM (-12) - moveml d2-d4,sp@ - movel a6@(8),d0 - movel a6@(12),d1 - clrl d2 | clear p - moveq IMM (31),d4 -L1: addl d0,d0 | shift reg pair (p,a) one bit left - addxl d2,d2 - movl d2,d3 | subtract b from p, store in tmp. - subl d1,d3 - jcs L2 | if no carry, - bset IMM (0),d0 | set the low order bit of a to 1, - movl d3,d2 | and store tmp in p. -L2: subql IMM (1),d4 - jcc L1 - moveml sp@,d2-d4 | restore data registers - unlk a6 | and return - rts -#endif /* __mcoldfire__ */ - -#endif /* L_udivsi3 */ - -#ifdef L_divsi3 - .text - FUNC(__divsi3) - .globl SYM (__divsi3) -SYM (__divsi3): - movel d2, sp@- - - moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */ - movel sp@(12), d1 /* d1 = divisor */ - jpl L1 - negl d1 -#ifndef __mcoldfire__ - negb d2 /* change sign because divisor <0 */ -#else - negl d2 /* change sign because divisor <0 */ -#endif -L1: movel sp@(8), d0 /* d0 = dividend */ - jpl L2 - negl d0 -#ifndef __mcoldfire__ - negb d2 -#else - negl d2 -#endif - -L2: movel d1, sp@- - movel d0, sp@- - PICCALL SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */ - addql IMM (8), sp - - tstb d2 - jpl L3 - negl d0 - -L3: movel sp@+, d2 - rts -#endif /* L_divsi3 */ - -#ifdef L_umodsi3 - .text - FUNC(__umodsi3) - .globl SYM (__umodsi3) -SYM (__umodsi3): - movel sp@(8), d1 /* d1 = divisor */ - movel sp@(4), d0 /* d0 = dividend */ - movel d1, sp@- - movel d0, sp@- - PICCALL SYM (__udivsi3) - addql IMM (8), sp - movel sp@(8), d1 /* d1 = divisor */ -#ifndef __mcoldfire__ - movel d1, sp@- - movel d0, sp@- - PICCALL SYM (__mulsi3) /* d0 = (a/b)*b */ - addql IMM (8), sp -#else - mulsl d1,d0 -#endif - movel sp@(4), d1 /* d1 = dividend */ - subl d0, d1 /* d1 = a - (a/b)*b */ - movel d1, d0 - rts -#endif /* L_umodsi3 */ - -#ifdef L_modsi3 - .text - FUNC(__modsi3) - .globl SYM (__modsi3) -SYM (__modsi3): - movel sp@(8), d1 /* d1 = divisor */ - movel sp@(4), d0 /* d0 = dividend */ - movel d1, sp@- - movel d0, sp@- - PICCALL SYM (__divsi3) - addql IMM (8), sp - movel sp@(8), d1 /* d1 = divisor */ -#ifndef __mcoldfire__ - movel d1, sp@- - movel d0, sp@- - PICCALL SYM (__mulsi3) /* d0 = (a/b)*b */ - addql IMM (8), sp -#else - mulsl d1,d0 -#endif - movel sp@(4), d1 /* d1 = dividend */ - subl d0, d1 /* d1 = a - (a/b)*b */ - movel d1, d0 - rts -#endif /* L_modsi3 */ - - -#ifdef L_double - - .globl SYM (_fpCCR) - .globl $_exception_handler - -QUIET_NaN = 0xffffffff - -D_MAX_EXP = 0x07ff -D_BIAS = 1022 -DBL_MAX_EXP = D_MAX_EXP - D_BIAS -DBL_MIN_EXP = 1 - D_BIAS -DBL_MANT_DIG = 53 - -INEXACT_RESULT = 0x0001 -UNDERFLOW = 0x0002 -OVERFLOW = 0x0004 -DIVIDE_BY_ZERO = 0x0008 -INVALID_OPERATION = 0x0010 - -DOUBLE_FLOAT = 2 - -NOOP = 0 -ADD = 1 -MULTIPLY = 2 -DIVIDE = 3 -NEGATE = 4 -COMPARE = 5 -EXTENDSFDF = 6 -TRUNCDFSF = 7 - -UNKNOWN = -1 -ROUND_TO_NEAREST = 0 | round result to nearest representable value -ROUND_TO_ZERO = 1 | round result towards zero -ROUND_TO_PLUS = 2 | round result towards plus infinity -ROUND_TO_MINUS = 3 | round result towards minus infinity - -| Entry points: - - .globl SYM (__adddf3) - .globl SYM (__subdf3) - .globl SYM (__muldf3) - .globl SYM (__divdf3) - .globl SYM (__negdf2) - .globl SYM (__cmpdf2) - .globl SYM (__cmpdf2_internal) - .hidden SYM (__cmpdf2_internal) - - .text - .even - -| These are common routines to return and signal exceptions. - -Ld$den: -| Return and signal a denormalized number - orl d7,d0 - movew IMM (INEXACT_RESULT+UNDERFLOW),d7 - moveq IMM (DOUBLE_FLOAT),d6 - PICJUMP $_exception_handler - -Ld$infty: -Ld$overflow: -| Return a properly signed INFINITY and set the exception flags - movel IMM (0x7ff00000),d0 - movel IMM (0),d1 - orl d7,d0 - movew IMM (INEXACT_RESULT+OVERFLOW),d7 - moveq IMM (DOUBLE_FLOAT),d6 - PICJUMP $_exception_handler - -Ld$underflow: -| Return 0 and set the exception flags - movel IMM (0),d0 - movel d0,d1 - movew IMM (INEXACT_RESULT+UNDERFLOW),d7 - moveq IMM (DOUBLE_FLOAT),d6 - PICJUMP $_exception_handler - -Ld$inop: -| Return a quiet NaN and set the exception flags - movel IMM (QUIET_NaN),d0 - movel d0,d1 - movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7 - moveq IMM (DOUBLE_FLOAT),d6 - PICJUMP $_exception_handler - -Ld$div$0: -| Return a properly signed INFINITY and set the exception flags - movel IMM (0x7ff00000),d0 - movel IMM (0),d1 - orl d7,d0 - movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7 - moveq IMM (DOUBLE_FLOAT),d6 - PICJUMP $_exception_handler - -|============================================================================= -|============================================================================= -| double precision routines -|============================================================================= -|============================================================================= - -| A double precision floating point number (double) has the format: -| -| struct _double { -| unsigned int sign : 1; /* sign bit */ -| unsigned int exponent : 11; /* exponent, shifted by 126 */ -| unsigned int fraction : 52; /* fraction */ -| } double; -| -| Thus sizeof(double) = 8 (64 bits). -| -| All the routines are callable from C programs, and return the result -| in the register pair d0-d1. They also preserve all registers except -| d0-d1 and a0-a1. - -|============================================================================= -| __subdf3 -|============================================================================= - -| double __subdf3(double, double); - FUNC(__subdf3) -SYM (__subdf3): - bchg IMM (31),sp@(12) | change sign of second operand - | and fall through, so we always add -|============================================================================= -| __adddf3 -|============================================================================= - -| double __adddf3(double, double); - FUNC(__adddf3) -SYM (__adddf3): -#ifndef __mcoldfire__ - link a6,IMM (0) | everything will be done in registers - moveml d2-d7,sp@- | save all data registers and a2 (but d0-d1) -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - movel a6@(8),d0 | get first operand - movel a6@(12),d1 | - movel a6@(16),d2 | get second operand - movel a6@(20),d3 | - - movel d0,d7 | get d0's sign bit in d7 ' - addl d1,d1 | check and clear sign bit of a, and gain one - addxl d0,d0 | bit of extra precision - beq Ladddf$b | if zero return second operand - - movel d2,d6 | save sign in d6 - addl d3,d3 | get rid of sign bit and gain one bit of - addxl d2,d2 | extra precision - beq Ladddf$a | if zero return first operand - - andl IMM (0x80000000),d7 | isolate a's sign bit ' - swap d6 | and also b's sign bit ' -#ifndef __mcoldfire__ - andw IMM (0x8000),d6 | - orw d6,d7 | and combine them into d7, so that a's sign ' - | bit is in the high word and b's is in the ' - | low word, so d6 is free to be used -#else - andl IMM (0x8000),d6 - orl d6,d7 -#endif - movel d7,a0 | now save d7 into a0, so d7 is free to - | be used also - -| Get the exponents and check for denormalized and/or infinity. - - movel IMM (0x001fffff),d6 | mask for the fraction - movel IMM (0x00200000),d7 | mask to put hidden bit back - - movel d0,d4 | - andl d6,d0 | get fraction in d0 - notl d6 | make d6 into mask for the exponent - andl d6,d4 | get exponent in d4 - beq Ladddf$a$den | branch if a is denormalized - cmpl d6,d4 | check for INFINITY or NaN - beq Ladddf$nf | - orl d7,d0 | and put hidden bit back -Ladddf$1: - swap d4 | shift right exponent so that it starts -#ifndef __mcoldfire__ - lsrw IMM (5),d4 | in bit 0 and not bit 20 -#else - lsrl IMM (5),d4 | in bit 0 and not bit 20 -#endif -| Now we have a's exponent in d4 and fraction in d0-d1 ' - movel d2,d5 | save b to get exponent - andl d6,d5 | get exponent in d5 - beq Ladddf$b$den | branch if b is denormalized - cmpl d6,d5 | check for INFINITY or NaN - beq Ladddf$nf - notl d6 | make d6 into mask for the fraction again - andl d6,d2 | and get fraction in d2 - orl d7,d2 | and put hidden bit back -Ladddf$2: - swap d5 | shift right exponent so that it starts -#ifndef __mcoldfire__ - lsrw IMM (5),d5 | in bit 0 and not bit 20 -#else - lsrl IMM (5),d5 | in bit 0 and not bit 20 -#endif - -| Now we have b's exponent in d5 and fraction in d2-d3. ' - -| The situation now is as follows: the signs are combined in a0, the -| numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a) -| and d5 (b). To do the rounding correctly we need to keep all the -| bits until the end, so we need to use d0-d1-d2-d3 for the first number -| and d4-d5-d6-d7 for the second. To do this we store (temporarily) the -| exponents in a2-a3. - -#ifndef __mcoldfire__ - moveml a2-a3,sp@- | save the address registers -#else - movel a2,sp@- - movel a3,sp@- - movel a4,sp@- -#endif - - movel d4,a2 | save the exponents - movel d5,a3 | - - movel IMM (0),d7 | and move the numbers around - movel d7,d6 | - movel d3,d5 | - movel d2,d4 | - movel d7,d3 | - movel d7,d2 | - -| Here we shift the numbers until the exponents are the same, and put -| the largest exponent in a2. -#ifndef __mcoldfire__ - exg d4,a2 | get exponents back - exg d5,a3 | - cmpw d4,d5 | compare the exponents -#else - movel d4,a4 | get exponents back - movel a2,d4 - movel a4,a2 - movel d5,a4 - movel a3,d5 - movel a4,a3 - cmpl d4,d5 | compare the exponents -#endif - beq Ladddf$3 | if equal don't shift ' - bhi 9f | branch if second exponent is higher - -| Here we have a's exponent larger than b's, so we have to shift b. We do -| this by using as counter d2: -1: movew d4,d2 | move largest exponent to d2 -#ifndef __mcoldfire__ - subw d5,d2 | and subtract second exponent - exg d4,a2 | get back the longs we saved - exg d5,a3 | -#else - subl d5,d2 | and subtract second exponent - movel d4,a4 | get back the longs we saved - movel a2,d4 - movel a4,a2 - movel d5,a4 - movel a3,d5 - movel a4,a3 -#endif -| if difference is too large we don't shift (actually, we can just exit) ' -#ifndef __mcoldfire__ - cmpw IMM (DBL_MANT_DIG+2),d2 -#else - cmpl IMM (DBL_MANT_DIG+2),d2 -#endif - bge Ladddf$b$small -#ifndef __mcoldfire__ - cmpw IMM (32),d2 | if difference >= 32, shift by longs -#else - cmpl IMM (32),d2 | if difference >= 32, shift by longs -#endif - bge 5f -2: -#ifndef __mcoldfire__ - cmpw IMM (16),d2 | if difference >= 16, shift by words -#else - cmpl IMM (16),d2 | if difference >= 16, shift by words -#endif - bge 6f - bra 3f | enter dbra loop - -4: -#ifndef __mcoldfire__ - lsrl IMM (1),d4 - roxrl IMM (1),d5 - roxrl IMM (1),d6 - roxrl IMM (1),d7 -#else - lsrl IMM (1),d7 - btst IMM (0),d6 - beq 10f - bset IMM (31),d7 -10: lsrl IMM (1),d6 - btst IMM (0),d5 - beq 11f - bset IMM (31),d6 -11: lsrl IMM (1),d5 - btst IMM (0),d4 - beq 12f - bset IMM (31),d5 -12: lsrl IMM (1),d4 -#endif -3: -#ifndef __mcoldfire__ - dbra d2,4b -#else - subql IMM (1),d2 - bpl 4b -#endif - movel IMM (0),d2 - movel d2,d3 - bra Ladddf$4 -5: - movel d6,d7 - movel d5,d6 - movel d4,d5 - movel IMM (0),d4 -#ifndef __mcoldfire__ - subw IMM (32),d2 -#else - subl IMM (32),d2 -#endif - bra 2b -6: - movew d6,d7 - swap d7 - movew d5,d6 - swap d6 - movew d4,d5 - swap d5 - movew IMM (0),d4 - swap d4 -#ifndef __mcoldfire__ - subw IMM (16),d2 -#else - subl IMM (16),d2 -#endif - bra 3b - -9: -#ifndef __mcoldfire__ - exg d4,d5 - movew d4,d6 - subw d5,d6 | keep d5 (largest exponent) in d4 - exg d4,a2 - exg d5,a3 -#else - movel d5,d6 - movel d4,d5 - movel d6,d4 - subl d5,d6 - movel d4,a4 - movel a2,d4 - movel a4,a2 - movel d5,a4 - movel a3,d5 - movel a4,a3 -#endif -| if difference is too large we don't shift (actually, we can just exit) ' -#ifndef __mcoldfire__ - cmpw IMM (DBL_MANT_DIG+2),d6 -#else - cmpl IMM (DBL_MANT_DIG+2),d6 -#endif - bge Ladddf$a$small -#ifndef __mcoldfire__ - cmpw IMM (32),d6 | if difference >= 32, shift by longs -#else - cmpl IMM (32),d6 | if difference >= 32, shift by longs -#endif - bge 5f -2: -#ifndef __mcoldfire__ - cmpw IMM (16),d6 | if difference >= 16, shift by words -#else - cmpl IMM (16),d6 | if difference >= 16, shift by words -#endif - bge 6f - bra 3f | enter dbra loop - -4: -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 -#else - lsrl IMM (1),d3 - btst IMM (0),d2 - beq 10f - bset IMM (31),d3 -10: lsrl IMM (1),d2 - btst IMM (0),d1 - beq 11f - bset IMM (31),d2 -11: lsrl IMM (1),d1 - btst IMM (0),d0 - beq 12f - bset IMM (31),d1 -12: lsrl IMM (1),d0 -#endif -3: -#ifndef __mcoldfire__ - dbra d6,4b -#else - subql IMM (1),d6 - bpl 4b -#endif - movel IMM (0),d7 - movel d7,d6 - bra Ladddf$4 -5: - movel d2,d3 - movel d1,d2 - movel d0,d1 - movel IMM (0),d0 -#ifndef __mcoldfire__ - subw IMM (32),d6 -#else - subl IMM (32),d6 -#endif - bra 2b -6: - movew d2,d3 - swap d3 - movew d1,d2 - swap d2 - movew d0,d1 - swap d1 - movew IMM (0),d0 - swap d0 -#ifndef __mcoldfire__ - subw IMM (16),d6 -#else - subl IMM (16),d6 -#endif - bra 3b -Ladddf$3: -#ifndef __mcoldfire__ - exg d4,a2 - exg d5,a3 -#else - movel d4,a4 - movel a2,d4 - movel a4,a2 - movel d5,a4 - movel a3,d5 - movel a4,a3 -#endif -Ladddf$4: -| Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and -| the signs in a4. - -| Here we have to decide whether to add or subtract the numbers: -#ifndef __mcoldfire__ - exg d7,a0 | get the signs - exg d6,a3 | a3 is free to be used -#else - movel d7,a4 - movel a0,d7 - movel a4,a0 - movel d6,a4 - movel a3,d6 - movel a4,a3 -#endif - movel d7,d6 | - movew IMM (0),d7 | get a's sign in d7 ' - swap d6 | - movew IMM (0),d6 | and b's sign in d6 ' - eorl d7,d6 | compare the signs - bmi Lsubdf$0 | if the signs are different we have - | to subtract -#ifndef __mcoldfire__ - exg d7,a0 | else we add the numbers - exg d6,a3 | -#else - movel d7,a4 - movel a0,d7 - movel a4,a0 - movel d6,a4 - movel a3,d6 - movel a4,a3 -#endif - addl d7,d3 | - addxl d6,d2 | - addxl d5,d1 | - addxl d4,d0 | - - movel a2,d4 | return exponent to d4 - movel a0,d7 | - andl IMM (0x80000000),d7 | d7 now has the sign - -#ifndef __mcoldfire__ - moveml sp@+,a2-a3 -#else - movel sp@+,a4 - movel sp@+,a3 - movel sp@+,a2 -#endif - -| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider -| the case of denormalized numbers in the rounding routine itself). -| As in the addition (not in the subtraction!) we could have set -| one more bit we check this: - btst IMM (DBL_MANT_DIG+1),d0 - beq 1f -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 - addw IMM (1),d4 -#else - lsrl IMM (1),d3 - btst IMM (0),d2 - beq 10f - bset IMM (31),d3 -10: lsrl IMM (1),d2 - btst IMM (0),d1 - beq 11f - bset IMM (31),d2 -11: lsrl IMM (1),d1 - btst IMM (0),d0 - beq 12f - bset IMM (31),d1 -12: lsrl IMM (1),d0 - addl IMM (1),d4 -#endif -1: - lea pc@(Ladddf$5),a0 | to return from rounding routine - PICLEA SYM (_fpCCR),a1 | check the rounding mode -#ifdef __mcoldfire__ - clrl d6 -#endif - movew a1@(6),d6 | rounding mode in d6 - beq Lround$to$nearest -#ifndef __mcoldfire__ - cmpw IMM (ROUND_TO_PLUS),d6 -#else - cmpl IMM (ROUND_TO_PLUS),d6 -#endif - bhi Lround$to$minus - blt Lround$to$zero - bra Lround$to$plus -Ladddf$5: -| Put back the exponent and check for overflow -#ifndef __mcoldfire__ - cmpw IMM (0x7ff),d4 | is the exponent big? -#else - cmpl IMM (0x7ff),d4 | is the exponent big? -#endif - bge 1f - bclr IMM (DBL_MANT_DIG-1),d0 -#ifndef __mcoldfire__ - lslw IMM (4),d4 | put exponent back into position -#else - lsll IMM (4),d4 | put exponent back into position -#endif - swap d0 | -#ifndef __mcoldfire__ - orw d4,d0 | -#else - orl d4,d0 | -#endif - swap d0 | - bra Ladddf$ret -1: - moveq IMM (ADD),d5 - bra Ld$overflow - -Lsubdf$0: -| Here we do the subtraction. -#ifndef __mcoldfire__ - exg d7,a0 | put sign back in a0 - exg d6,a3 | -#else - movel d7,a4 - movel a0,d7 - movel a4,a0 - movel d6,a4 - movel a3,d6 - movel a4,a3 -#endif - subl d7,d3 | - subxl d6,d2 | - subxl d5,d1 | - subxl d4,d0 | - beq Ladddf$ret$1 | if zero just exit - bpl 1f | if positive skip the following - movel a0,d7 | - bchg IMM (31),d7 | change sign bit in d7 - movel d7,a0 | - negl d3 | - negxl d2 | - negxl d1 | and negate result - negxl d0 | -1: - movel a2,d4 | return exponent to d4 - movel a0,d7 - andl IMM (0x80000000),d7 | isolate sign bit -#ifndef __mcoldfire__ - moveml sp@+,a2-a3 | -#else - movel sp@+,a4 - movel sp@+,a3 - movel sp@+,a2 -#endif - -| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider -| the case of denormalized numbers in the rounding routine itself). -| As in the addition (not in the subtraction!) we could have set -| one more bit we check this: - btst IMM (DBL_MANT_DIG+1),d0 - beq 1f -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 - addw IMM (1),d4 -#else - lsrl IMM (1),d3 - btst IMM (0),d2 - beq 10f - bset IMM (31),d3 -10: lsrl IMM (1),d2 - btst IMM (0),d1 - beq 11f - bset IMM (31),d2 -11: lsrl IMM (1),d1 - btst IMM (0),d0 - beq 12f - bset IMM (31),d1 -12: lsrl IMM (1),d0 - addl IMM (1),d4 -#endif -1: - lea pc@(Lsubdf$1),a0 | to return from rounding routine - PICLEA SYM (_fpCCR),a1 | check the rounding mode -#ifdef __mcoldfire__ - clrl d6 -#endif - movew a1@(6),d6 | rounding mode in d6 - beq Lround$to$nearest -#ifndef __mcoldfire__ - cmpw IMM (ROUND_TO_PLUS),d6 -#else - cmpl IMM (ROUND_TO_PLUS),d6 -#endif - bhi Lround$to$minus - blt Lround$to$zero - bra Lround$to$plus -Lsubdf$1: -| Put back the exponent and sign (we don't have overflow). ' - bclr IMM (DBL_MANT_DIG-1),d0 -#ifndef __mcoldfire__ - lslw IMM (4),d4 | put exponent back into position -#else - lsll IMM (4),d4 | put exponent back into position -#endif - swap d0 | -#ifndef __mcoldfire__ - orw d4,d0 | -#else - orl d4,d0 | -#endif - swap d0 | - bra Ladddf$ret - -| If one of the numbers was too small (difference of exponents >= -| DBL_MANT_DIG+1) we return the other (and now we don't have to ' -| check for finiteness or zero). -Ladddf$a$small: -#ifndef __mcoldfire__ - moveml sp@+,a2-a3 -#else - movel sp@+,a4 - movel sp@+,a3 - movel sp@+,a2 -#endif - movel a6@(16),d0 - movel a6@(20),d1 - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | restore data registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | and return - rts - -Ladddf$b$small: -#ifndef __mcoldfire__ - moveml sp@+,a2-a3 -#else - movel sp@+,a4 - movel sp@+,a3 - movel sp@+,a2 -#endif - movel a6@(8),d0 - movel a6@(12),d1 - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | restore data registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | and return - rts - -Ladddf$a$den: - movel d7,d4 | d7 contains 0x00200000 - bra Ladddf$1 - -Ladddf$b$den: - movel d7,d5 | d7 contains 0x00200000 - notl d6 - bra Ladddf$2 - -Ladddf$b: -| Return b (if a is zero) - movel d2,d0 - movel d3,d1 - bne 1f | Check if b is -0 - cmpl IMM (0x80000000),d0 - bne 1f - andl IMM (0x80000000),d7 | Use the sign of a - clrl d0 - bra Ladddf$ret -Ladddf$a: - movel a6@(8),d0 - movel a6@(12),d1 -1: - moveq IMM (ADD),d5 -| Check for NaN and +/-INFINITY. - movel d0,d7 | - andl IMM (0x80000000),d7 | - bclr IMM (31),d0 | - cmpl IMM (0x7ff00000),d0 | - bge 2f | - movel d0,d0 | check for zero, since we don't ' - bne Ladddf$ret | want to return -0 by mistake - bclr IMM (31),d7 | - bra Ladddf$ret | -2: - andl IMM (0x000fffff),d0 | check for NaN (nonzero fraction) - orl d1,d0 | - bne Ld$inop | - bra Ld$infty | - -Ladddf$ret$1: -#ifndef __mcoldfire__ - moveml sp@+,a2-a3 | restore regs and exit -#else - movel sp@+,a4 - movel sp@+,a3 - movel sp@+,a2 -#endif - -Ladddf$ret: -| Normal exit. - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ - orl d7,d0 | put sign bit back -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts - -Ladddf$ret$den: -| Return a denormalized number. -#ifndef __mcoldfire__ - lsrl IMM (1),d0 | shift right once more - roxrl IMM (1),d1 | -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 -#endif - bra Ladddf$ret - -Ladddf$nf: - moveq IMM (ADD),d5 -| This could be faster but it is not worth the effort, since it is not -| executed very often. We sacrifice speed for clarity here. - movel a6@(8),d0 | get the numbers back (remember that we - movel a6@(12),d1 | did some processing already) - movel a6@(16),d2 | - movel a6@(20),d3 | - movel IMM (0x7ff00000),d4 | useful constant (INFINITY) - movel d0,d7 | save sign bits - movel d2,d6 | - bclr IMM (31),d0 | clear sign bits - bclr IMM (31),d2 | -| We know that one of them is either NaN of +/-INFINITY -| Check for NaN (if either one is NaN return NaN) - cmpl d4,d0 | check first a (d0) - bhi Ld$inop | if d0 > 0x7ff00000 or equal and - bne 2f - tstl d1 | d1 > 0, a is NaN - bne Ld$inop | -2: cmpl d4,d2 | check now b (d1) - bhi Ld$inop | - bne 3f - tstl d3 | - bne Ld$inop | -3: -| Now comes the check for +/-INFINITY. We know that both are (maybe not -| finite) numbers, but we have to check if both are infinite whether we -| are adding or subtracting them. - eorl d7,d6 | to check sign bits - bmi 1f - andl IMM (0x80000000),d7 | get (common) sign bit - bra Ld$infty -1: -| We know one (or both) are infinite, so we test for equality between the -| two numbers (if they are equal they have to be infinite both, so we -| return NaN). - cmpl d2,d0 | are both infinite? - bne 1f | if d0 <> d2 they are not equal - cmpl d3,d1 | if d0 == d2 test d3 and d1 - beq Ld$inop | if equal return NaN -1: - andl IMM (0x80000000),d7 | get a's sign bit ' - cmpl d4,d0 | test now for infinity - beq Ld$infty | if a is INFINITY return with this sign - bchg IMM (31),d7 | else we know b is INFINITY and has - bra Ld$infty | the opposite sign - -|============================================================================= -| __muldf3 -|============================================================================= - -| double __muldf3(double, double); - FUNC(__muldf3) -SYM (__muldf3): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - movel a6@(8),d0 | get a into d0-d1 - movel a6@(12),d1 | - movel a6@(16),d2 | and b into d2-d3 - movel a6@(20),d3 | - movel d0,d7 | d7 will hold the sign of the product - eorl d2,d7 | - andl IMM (0x80000000),d7 | - movel d7,a0 | save sign bit into a0 - movel IMM (0x7ff00000),d7 | useful constant (+INFINITY) - movel d7,d6 | another (mask for fraction) - notl d6 | - bclr IMM (31),d0 | get rid of a's sign bit ' - movel d0,d4 | - orl d1,d4 | - beq Lmuldf$a$0 | branch if a is zero - movel d0,d4 | - bclr IMM (31),d2 | get rid of b's sign bit ' - movel d2,d5 | - orl d3,d5 | - beq Lmuldf$b$0 | branch if b is zero - movel d2,d5 | - cmpl d7,d0 | is a big? - bhi Lmuldf$inop | if a is NaN return NaN - beq Lmuldf$a$nf | we still have to check d1 and b ... - cmpl d7,d2 | now compare b with INFINITY - bhi Lmuldf$inop | is b NaN? - beq Lmuldf$b$nf | we still have to check d3 ... -| Here we have both numbers finite and nonzero (and with no sign bit). -| Now we get the exponents into d4 and d5. - andl d7,d4 | isolate exponent in d4 - beq Lmuldf$a$den | if exponent zero, have denormalized - andl d6,d0 | isolate fraction - orl IMM (0x00100000),d0 | and put hidden bit back - swap d4 | I like exponents in the first byte -#ifndef __mcoldfire__ - lsrw IMM (4),d4 | -#else - lsrl IMM (4),d4 | -#endif -Lmuldf$1: - andl d7,d5 | - beq Lmuldf$b$den | - andl d6,d2 | - orl IMM (0x00100000),d2 | and put hidden bit back - swap d5 | -#ifndef __mcoldfire__ - lsrw IMM (4),d5 | -#else - lsrl IMM (4),d5 | -#endif -Lmuldf$2: | -#ifndef __mcoldfire__ - addw d5,d4 | add exponents - subw IMM (D_BIAS+1),d4 | and subtract bias (plus one) -#else - addl d5,d4 | add exponents - subl IMM (D_BIAS+1),d4 | and subtract bias (plus one) -#endif - -| We are now ready to do the multiplication. The situation is as follows: -| both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were -| denormalized to start with!), which means that in the product bit 104 -| (which will correspond to bit 8 of the fourth long) is set. - -| Here we have to do the product. -| To do it we have to juggle the registers back and forth, as there are not -| enough to keep everything in them. So we use the address registers to keep -| some intermediate data. - -#ifndef __mcoldfire__ - moveml a2-a3,sp@- | save a2 and a3 for temporary use -#else - movel a2,sp@- - movel a3,sp@- - movel a4,sp@- -#endif - movel IMM (0),a2 | a2 is a null register - movel d4,a3 | and a3 will preserve the exponent - -| First, shift d2-d3 so bit 20 becomes bit 31: -#ifndef __mcoldfire__ - rorl IMM (5),d2 | rotate d2 5 places right - swap d2 | and swap it - rorl IMM (5),d3 | do the same thing with d3 - swap d3 | - movew d3,d6 | get the rightmost 11 bits of d3 - andw IMM (0x07ff),d6 | - orw d6,d2 | and put them into d2 - andw IMM (0xf800),d3 | clear those bits in d3 -#else - moveq IMM (11),d7 | left shift d2 11 bits - lsll d7,d2 - movel d3,d6 | get a copy of d3 - lsll d7,d3 | left shift d3 11 bits - andl IMM (0xffe00000),d6 | get the top 11 bits of d3 - moveq IMM (21),d7 | right shift them 21 bits - lsrl d7,d6 - orl d6,d2 | stick them at the end of d2 -#endif - - movel d2,d6 | move b into d6-d7 - movel d3,d7 | move a into d4-d5 - movel d0,d4 | and clear d0-d1-d2-d3 (to put result) - movel d1,d5 | - movel IMM (0),d3 | - movel d3,d2 | - movel d3,d1 | - movel d3,d0 | - -| We use a1 as counter: - movel IMM (DBL_MANT_DIG-1),a1 -#ifndef __mcoldfire__ - exg d7,a1 -#else - movel d7,a4 - movel a1,d7 - movel a4,a1 -#endif - -1: -#ifndef __mcoldfire__ - exg d7,a1 | put counter back in a1 -#else - movel d7,a4 - movel a1,d7 - movel a4,a1 -#endif - addl d3,d3 | shift sum once left - addxl d2,d2 | - addxl d1,d1 | - addxl d0,d0 | - addl d7,d7 | - addxl d6,d6 | - bcc 2f | if bit clear skip the following -#ifndef __mcoldfire__ - exg d7,a2 | -#else - movel d7,a4 - movel a2,d7 - movel a4,a2 -#endif - addl d5,d3 | else add a to the sum - addxl d4,d2 | - addxl d7,d1 | - addxl d7,d0 | -#ifndef __mcoldfire__ - exg d7,a2 | -#else - movel d7,a4 - movel a2,d7 - movel a4,a2 -#endif -2: -#ifndef __mcoldfire__ - exg d7,a1 | put counter in d7 - dbf d7,1b | decrement and branch -#else - movel d7,a4 - movel a1,d7 - movel a4,a1 - subql IMM (1),d7 - bpl 1b -#endif - - movel a3,d4 | restore exponent -#ifndef __mcoldfire__ - moveml sp@+,a2-a3 -#else - movel sp@+,a4 - movel sp@+,a3 - movel sp@+,a2 -#endif - -| Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The -| first thing to do now is to normalize it so bit 8 becomes bit -| DBL_MANT_DIG-32 (to do the rounding); later we will shift right. - swap d0 - swap d1 - movew d1,d0 - swap d2 - movew d2,d1 - swap d3 - movew d3,d2 - movew IMM (0),d3 -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 -#else - moveq IMM (29),d6 - lsrl IMM (3),d3 - movel d2,d7 - lsll d6,d7 - orl d7,d3 - lsrl IMM (3),d2 - movel d1,d7 - lsll d6,d7 - orl d7,d2 - lsrl IMM (3),d1 - movel d0,d7 - lsll d6,d7 - orl d7,d1 - lsrl IMM (3),d0 -#endif - -| Now round, check for over- and underflow, and exit. - movel a0,d7 | get sign bit back into d7 - moveq IMM (MULTIPLY),d5 - - btst IMM (DBL_MANT_DIG+1-32),d0 - beq Lround$exit -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - addw IMM (1),d4 -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 - addl IMM (1),d4 -#endif - bra Lround$exit - -Lmuldf$inop: - moveq IMM (MULTIPLY),d5 - bra Ld$inop - -Lmuldf$b$nf: - moveq IMM (MULTIPLY),d5 - movel a0,d7 | get sign bit back into d7 - tstl d3 | we know d2 == 0x7ff00000, so check d3 - bne Ld$inop | if d3 <> 0 b is NaN - bra Ld$overflow | else we have overflow (since a is finite) - -Lmuldf$a$nf: - moveq IMM (MULTIPLY),d5 - movel a0,d7 | get sign bit back into d7 - tstl d1 | we know d0 == 0x7ff00000, so check d1 - bne Ld$inop | if d1 <> 0 a is NaN - bra Ld$overflow | else signal overflow - -| If either number is zero return zero, unless the other is +/-INFINITY or -| NaN, in which case we return NaN. -Lmuldf$b$0: - moveq IMM (MULTIPLY),d5 -#ifndef __mcoldfire__ - exg d2,d0 | put b (==0) into d0-d1 - exg d3,d1 | and a (with sign bit cleared) into d2-d3 - movel a0,d0 | set result sign -#else - movel d0,d2 | put a into d2-d3 - movel d1,d3 - movel a0,d0 | put result zero into d0-d1 - movq IMM(0),d1 -#endif - bra 1f -Lmuldf$a$0: - movel a0,d0 | set result sign - movel a6@(16),d2 | put b into d2-d3 again - movel a6@(20),d3 | - bclr IMM (31),d2 | clear sign bit -1: cmpl IMM (0x7ff00000),d2 | check for non-finiteness - bge Ld$inop | in case NaN or +/-INFINITY return NaN - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts - -| If a number is denormalized we put an exponent of 1 but do not put the -| hidden bit back into the fraction; instead we shift left until bit 21 -| (the hidden bit) is set, adjusting the exponent accordingly. We do this -| to ensure that the product of the fractions is close to 1. -Lmuldf$a$den: - movel IMM (1),d4 - andl d6,d0 -1: addl d1,d1 | shift a left until bit 20 is set - addxl d0,d0 | -#ifndef __mcoldfire__ - subw IMM (1),d4 | and adjust exponent -#else - subl IMM (1),d4 | and adjust exponent -#endif - btst IMM (20),d0 | - bne Lmuldf$1 | - bra 1b - -Lmuldf$b$den: - movel IMM (1),d5 - andl d6,d2 -1: addl d3,d3 | shift b left until bit 20 is set - addxl d2,d2 | -#ifndef __mcoldfire__ - subw IMM (1),d5 | and adjust exponent -#else - subql IMM (1),d5 | and adjust exponent -#endif - btst IMM (20),d2 | - bne Lmuldf$2 | - bra 1b - - -|============================================================================= -| __divdf3 -|============================================================================= - -| double __divdf3(double, double); - FUNC(__divdf3) -SYM (__divdf3): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - movel a6@(8),d0 | get a into d0-d1 - movel a6@(12),d1 | - movel a6@(16),d2 | and b into d2-d3 - movel a6@(20),d3 | - movel d0,d7 | d7 will hold the sign of the result - eorl d2,d7 | - andl IMM (0x80000000),d7 - movel d7,a0 | save sign into a0 - movel IMM (0x7ff00000),d7 | useful constant (+INFINITY) - movel d7,d6 | another (mask for fraction) - notl d6 | - bclr IMM (31),d0 | get rid of a's sign bit ' - movel d0,d4 | - orl d1,d4 | - beq Ldivdf$a$0 | branch if a is zero - movel d0,d4 | - bclr IMM (31),d2 | get rid of b's sign bit ' - movel d2,d5 | - orl d3,d5 | - beq Ldivdf$b$0 | branch if b is zero - movel d2,d5 - cmpl d7,d0 | is a big? - bhi Ldivdf$inop | if a is NaN return NaN - beq Ldivdf$a$nf | if d0 == 0x7ff00000 we check d1 - cmpl d7,d2 | now compare b with INFINITY - bhi Ldivdf$inop | if b is NaN return NaN - beq Ldivdf$b$nf | if d2 == 0x7ff00000 we check d3 -| Here we have both numbers finite and nonzero (and with no sign bit). -| Now we get the exponents into d4 and d5 and normalize the numbers to -| ensure that the ratio of the fractions is around 1. We do this by -| making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit) -| set, even if they were denormalized to start with. -| Thus, the result will satisfy: 2 > result > 1/2. - andl d7,d4 | and isolate exponent in d4 - beq Ldivdf$a$den | if exponent is zero we have a denormalized - andl d6,d0 | and isolate fraction - orl IMM (0x00100000),d0 | and put hidden bit back - swap d4 | I like exponents in the first byte -#ifndef __mcoldfire__ - lsrw IMM (4),d4 | -#else - lsrl IMM (4),d4 | -#endif -Ldivdf$1: | - andl d7,d5 | - beq Ldivdf$b$den | - andl d6,d2 | - orl IMM (0x00100000),d2 - swap d5 | -#ifndef __mcoldfire__ - lsrw IMM (4),d5 | -#else - lsrl IMM (4),d5 | -#endif -Ldivdf$2: | -#ifndef __mcoldfire__ - subw d5,d4 | subtract exponents - addw IMM (D_BIAS),d4 | and add bias -#else - subl d5,d4 | subtract exponents - addl IMM (D_BIAS),d4 | and add bias -#endif - -| We are now ready to do the division. We have prepared things in such a way -| that the ratio of the fractions will be less than 2 but greater than 1/2. -| At this point the registers in use are: -| d0-d1 hold a (first operand, bit DBL_MANT_DIG-32=0, bit -| DBL_MANT_DIG-1-32=1) -| d2-d3 hold b (second operand, bit DBL_MANT_DIG-32=1) -| d4 holds the difference of the exponents, corrected by the bias -| a0 holds the sign of the ratio - -| To do the rounding correctly we need to keep information about the -| nonsignificant bits. One way to do this would be to do the division -| using four registers; another is to use two registers (as originally -| I did), but use a sticky bit to preserve information about the -| fractional part. Note that we can keep that info in a1, which is not -| used. - movel IMM (0),d6 | d6-d7 will hold the result - movel d6,d7 | - movel IMM (0),a1 | and a1 will hold the sticky bit - - movel IMM (DBL_MANT_DIG-32+1),d5 - -1: cmpl d0,d2 | is a < b? - bhi 3f | if b > a skip the following - beq 4f | if d0==d2 check d1 and d3 -2: subl d3,d1 | - subxl d2,d0 | a <-- a - b - bset d5,d6 | set the corresponding bit in d6 -3: addl d1,d1 | shift a by 1 - addxl d0,d0 | -#ifndef __mcoldfire__ - dbra d5,1b | and branch back -#else - subql IMM (1), d5 - bpl 1b -#endif - bra 5f -4: cmpl d1,d3 | here d0==d2, so check d1 and d3 - bhi 3b | if d1 > d2 skip the subtraction - bra 2b | else go do it -5: -| Here we have to start setting the bits in the second long. - movel IMM (31),d5 | again d5 is counter - -1: cmpl d0,d2 | is a < b? - bhi 3f | if b > a skip the following - beq 4f | if d0==d2 check d1 and d3 -2: subl d3,d1 | - subxl d2,d0 | a <-- a - b - bset d5,d7 | set the corresponding bit in d7 -3: addl d1,d1 | shift a by 1 - addxl d0,d0 | -#ifndef __mcoldfire__ - dbra d5,1b | and branch back -#else - subql IMM (1), d5 - bpl 1b -#endif - bra 5f -4: cmpl d1,d3 | here d0==d2, so check d1 and d3 - bhi 3b | if d1 > d2 skip the subtraction - bra 2b | else go do it -5: -| Now go ahead checking until we hit a one, which we store in d2. - movel IMM (DBL_MANT_DIG),d5 -1: cmpl d2,d0 | is a < b? - bhi 4f | if b < a, exit - beq 3f | if d0==d2 check d1 and d3 -2: addl d1,d1 | shift a by 1 - addxl d0,d0 | -#ifndef __mcoldfire__ - dbra d5,1b | and branch back -#else - subql IMM (1), d5 - bpl 1b -#endif - movel IMM (0),d2 | here no sticky bit was found - movel d2,d3 - bra 5f -3: cmpl d1,d3 | here d0==d2, so check d1 and d3 - bhi 2b | if d1 > d2 go back -4: -| Here put the sticky bit in d2-d3 (in the position which actually corresponds -| to it; if you don't do this the algorithm loses in some cases). ' - movel IMM (0),d2 - movel d2,d3 -#ifndef __mcoldfire__ - subw IMM (DBL_MANT_DIG),d5 - addw IMM (63),d5 - cmpw IMM (31),d5 -#else - subl IMM (DBL_MANT_DIG),d5 - addl IMM (63),d5 - cmpl IMM (31),d5 -#endif - bhi 2f -1: bset d5,d3 - bra 5f -#ifndef __mcoldfire__ - subw IMM (32),d5 -#else - subl IMM (32),d5 -#endif -2: bset d5,d2 -5: -| Finally we are finished! Move the longs in the address registers to -| their final destination: - movel d6,d0 - movel d7,d1 - movel IMM (0),d3 - -| Here we have finished the division, with the result in d0-d1-d2-d3, with -| 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set. -| If it is not, then definitely bit 21 is set. Normalize so bit 22 is -| not set: - btst IMM (DBL_MANT_DIG-32+1),d0 - beq 1f -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - roxrl IMM (1),d2 - roxrl IMM (1),d3 - addw IMM (1),d4 -#else - lsrl IMM (1),d3 - btst IMM (0),d2 - beq 10f - bset IMM (31),d3 -10: lsrl IMM (1),d2 - btst IMM (0),d1 - beq 11f - bset IMM (31),d2 -11: lsrl IMM (1),d1 - btst IMM (0),d0 - beq 12f - bset IMM (31),d1 -12: lsrl IMM (1),d0 - addl IMM (1),d4 -#endif -1: -| Now round, check for over- and underflow, and exit. - movel a0,d7 | restore sign bit to d7 - moveq IMM (DIVIDE),d5 - bra Lround$exit - -Ldivdf$inop: - moveq IMM (DIVIDE),d5 - bra Ld$inop - -Ldivdf$a$0: -| If a is zero check to see whether b is zero also. In that case return -| NaN; then check if b is NaN, and return NaN also in that case. Else -| return a properly signed zero. - moveq IMM (DIVIDE),d5 - bclr IMM (31),d2 | - movel d2,d4 | - orl d3,d4 | - beq Ld$inop | if b is also zero return NaN - cmpl IMM (0x7ff00000),d2 | check for NaN - bhi Ld$inop | - blt 1f | - tstl d3 | - bne Ld$inop | -1: movel a0,d0 | else return signed zero - moveq IMM(0),d1 | - PICLEA SYM (_fpCCR),a0 | clear exception flags - movew IMM (0),a0@ | -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | -#else - moveml sp@,d2-d7 | - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | - rts | - -Ldivdf$b$0: - moveq IMM (DIVIDE),d5 -| If we got here a is not zero. Check if a is NaN; in that case return NaN, -| else return +/-INFINITY. Remember that a is in d0 with the sign bit -| cleared already. - movel a0,d7 | put a's sign bit back in d7 ' - cmpl IMM (0x7ff00000),d0 | compare d0 with INFINITY - bhi Ld$inop | if larger it is NaN - tstl d1 | - bne Ld$inop | - bra Ld$div$0 | else signal DIVIDE_BY_ZERO - -Ldivdf$b$nf: - moveq IMM (DIVIDE),d5 -| If d2 == 0x7ff00000 we have to check d3. - tstl d3 | - bne Ld$inop | if d3 <> 0, b is NaN - bra Ld$underflow | else b is +/-INFINITY, so signal underflow - -Ldivdf$a$nf: - moveq IMM (DIVIDE),d5 -| If d0 == 0x7ff00000 we have to check d1. - tstl d1 | - bne Ld$inop | if d1 <> 0, a is NaN -| If a is INFINITY we have to check b - cmpl d7,d2 | compare b with INFINITY - bge Ld$inop | if b is NaN or INFINITY return NaN - tstl d3 | - bne Ld$inop | - bra Ld$overflow | else return overflow - -| If a number is denormalized we put an exponent of 1 but do not put the -| bit back into the fraction. -Ldivdf$a$den: - movel IMM (1),d4 - andl d6,d0 -1: addl d1,d1 | shift a left until bit 20 is set - addxl d0,d0 -#ifndef __mcoldfire__ - subw IMM (1),d4 | and adjust exponent -#else - subl IMM (1),d4 | and adjust exponent -#endif - btst IMM (DBL_MANT_DIG-32-1),d0 - bne Ldivdf$1 - bra 1b - -Ldivdf$b$den: - movel IMM (1),d5 - andl d6,d2 -1: addl d3,d3 | shift b left until bit 20 is set - addxl d2,d2 -#ifndef __mcoldfire__ - subw IMM (1),d5 | and adjust exponent -#else - subql IMM (1),d5 | and adjust exponent -#endif - btst IMM (DBL_MANT_DIG-32-1),d2 - bne Ldivdf$2 - bra 1b - -Lround$exit: -| This is a common exit point for __muldf3 and __divdf3. When they enter -| this point the sign of the result is in d7, the result in d0-d1, normalized -| so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4. - -| First check for underlow in the exponent: -#ifndef __mcoldfire__ - cmpw IMM (-DBL_MANT_DIG-1),d4 -#else - cmpl IMM (-DBL_MANT_DIG-1),d4 -#endif - blt Ld$underflow -| It could happen that the exponent is less than 1, in which case the -| number is denormalized. In this case we shift right and adjust the -| exponent until it becomes 1 or the fraction is zero (in the latter case -| we signal underflow and return zero). - movel d7,a0 | - movel IMM (0),d6 | use d6-d7 to collect bits flushed right - movel d6,d7 | use d6-d7 to collect bits flushed right -#ifndef __mcoldfire__ - cmpw IMM (1),d4 | if the exponent is less than 1 we -#else - cmpl IMM (1),d4 | if the exponent is less than 1 we -#endif - bge 2f | have to shift right (denormalize) -1: -#ifndef __mcoldfire__ - addw IMM (1),d4 | adjust the exponent - lsrl IMM (1),d0 | shift right once - roxrl IMM (1),d1 | - roxrl IMM (1),d2 | - roxrl IMM (1),d3 | - roxrl IMM (1),d6 | - roxrl IMM (1),d7 | - cmpw IMM (1),d4 | is the exponent 1 already? -#else - addl IMM (1),d4 | adjust the exponent - lsrl IMM (1),d7 - btst IMM (0),d6 - beq 13f - bset IMM (31),d7 -13: lsrl IMM (1),d6 - btst IMM (0),d3 - beq 14f - bset IMM (31),d6 -14: lsrl IMM (1),d3 - btst IMM (0),d2 - beq 10f - bset IMM (31),d3 -10: lsrl IMM (1),d2 - btst IMM (0),d1 - beq 11f - bset IMM (31),d2 -11: lsrl IMM (1),d1 - btst IMM (0),d0 - beq 12f - bset IMM (31),d1 -12: lsrl IMM (1),d0 - cmpl IMM (1),d4 | is the exponent 1 already? -#endif - beq 2f | if not loop back - bra 1b | - bra Ld$underflow | safety check, shouldn't execute ' -2: orl d6,d2 | this is a trick so we don't lose ' - orl d7,d3 | the bits which were flushed right - movel a0,d7 | get back sign bit into d7 -| Now call the rounding routine (which takes care of denormalized numbers): - lea pc@(Lround$0),a0 | to return from rounding routine - PICLEA SYM (_fpCCR),a1 | check the rounding mode -#ifdef __mcoldfire__ - clrl d6 -#endif - movew a1@(6),d6 | rounding mode in d6 - beq Lround$to$nearest -#ifndef __mcoldfire__ - cmpw IMM (ROUND_TO_PLUS),d6 -#else - cmpl IMM (ROUND_TO_PLUS),d6 -#endif - bhi Lround$to$minus - blt Lround$to$zero - bra Lround$to$plus -Lround$0: -| Here we have a correctly rounded result (either normalized or denormalized). - -| Here we should have either a normalized number or a denormalized one, and -| the exponent is necessarily larger or equal to 1 (so we don't have to ' -| check again for underflow!). We have to check for overflow or for a -| denormalized number (which also signals underflow). -| Check for overflow (i.e., exponent >= 0x7ff). -#ifndef __mcoldfire__ - cmpw IMM (0x07ff),d4 -#else - cmpl IMM (0x07ff),d4 -#endif - bge Ld$overflow -| Now check for a denormalized number (exponent==0): - movew d4,d4 - beq Ld$den -1: -| Put back the exponents and sign and return. -#ifndef __mcoldfire__ - lslw IMM (4),d4 | exponent back to fourth byte -#else - lsll IMM (4),d4 | exponent back to fourth byte -#endif - bclr IMM (DBL_MANT_DIG-32-1),d0 - swap d0 | and put back exponent -#ifndef __mcoldfire__ - orw d4,d0 | -#else - orl d4,d0 | -#endif - swap d0 | - orl d7,d0 | and sign also - - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts - -|============================================================================= -| __negdf2 -|============================================================================= - -| double __negdf2(double, double); - FUNC(__negdf2) -SYM (__negdf2): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - moveq IMM (NEGATE),d5 - movel a6@(8),d0 | get number to negate in d0-d1 - movel a6@(12),d1 | - bchg IMM (31),d0 | negate - movel d0,d2 | make a positive copy (for the tests) - bclr IMM (31),d2 | - movel d2,d4 | check for zero - orl d1,d4 | - beq 2f | if zero (either sign) return +zero - cmpl IMM (0x7ff00000),d2 | compare to +INFINITY - blt 1f | if finite, return - bhi Ld$inop | if larger (fraction not zero) is NaN - tstl d1 | if d2 == 0x7ff00000 check d1 - bne Ld$inop | - movel d0,d7 | else get sign and return INFINITY - andl IMM (0x80000000),d7 - bra Ld$infty -1: PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts -2: bclr IMM (31),d0 - bra 1b - -|============================================================================= -| __cmpdf2 -|============================================================================= - -GREATER = 1 -LESS = -1 -EQUAL = 0 - -| int __cmpdf2_internal(double, double, int); -SYM (__cmpdf2_internal): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- | save registers -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - moveq IMM (COMPARE),d5 - movel a6@(8),d0 | get first operand - movel a6@(12),d1 | - movel a6@(16),d2 | get second operand - movel a6@(20),d3 | -| First check if a and/or b are (+/-) zero and in that case clear -| the sign bit. - movel d0,d6 | copy signs into d6 (a) and d7(b) - bclr IMM (31),d0 | and clear signs in d0 and d2 - movel d2,d7 | - bclr IMM (31),d2 | - cmpl IMM (0x7ff00000),d0 | check for a == NaN - bhi Lcmpd$inop | if d0 > 0x7ff00000, a is NaN - beq Lcmpdf$a$nf | if equal can be INFINITY, so check d1 - movel d0,d4 | copy into d4 to test for zero - orl d1,d4 | - beq Lcmpdf$a$0 | -Lcmpdf$0: - cmpl IMM (0x7ff00000),d2 | check for b == NaN - bhi Lcmpd$inop | if d2 > 0x7ff00000, b is NaN - beq Lcmpdf$b$nf | if equal can be INFINITY, so check d3 - movel d2,d4 | - orl d3,d4 | - beq Lcmpdf$b$0 | -Lcmpdf$1: -| Check the signs - eorl d6,d7 - bpl 1f -| If the signs are not equal check if a >= 0 - tstl d6 - bpl Lcmpdf$a$gt$b | if (a >= 0 && b < 0) => a > b - bmi Lcmpdf$b$gt$a | if (a < 0 && b >= 0) => a < b -1: -| If the signs are equal check for < 0 - tstl d6 - bpl 1f -| If both are negative exchange them -#ifndef __mcoldfire__ - exg d0,d2 - exg d1,d3 -#else - movel d0,d7 - movel d2,d0 - movel d7,d2 - movel d1,d7 - movel d3,d1 - movel d7,d3 -#endif -1: -| Now that they are positive we just compare them as longs (does this also -| work for denormalized numbers?). - cmpl d0,d2 - bhi Lcmpdf$b$gt$a | |b| > |a| - bne Lcmpdf$a$gt$b | |b| < |a| -| If we got here d0 == d2, so we compare d1 and d3. - cmpl d1,d3 - bhi Lcmpdf$b$gt$a | |b| > |a| - bne Lcmpdf$a$gt$b | |b| < |a| -| If we got here a == b. - movel IMM (EQUAL),d0 -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | put back the registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts -Lcmpdf$a$gt$b: - movel IMM (GREATER),d0 -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | put back the registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts -Lcmpdf$b$gt$a: - movel IMM (LESS),d0 -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | put back the registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts - -Lcmpdf$a$0: - bclr IMM (31),d6 - bra Lcmpdf$0 -Lcmpdf$b$0: - bclr IMM (31),d7 - bra Lcmpdf$1 - -Lcmpdf$a$nf: - tstl d1 - bne Ld$inop - bra Lcmpdf$0 - -Lcmpdf$b$nf: - tstl d3 - bne Ld$inop - bra Lcmpdf$1 - -Lcmpd$inop: - movl a6@(24),d0 - moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 - moveq IMM (DOUBLE_FLOAT),d6 - PICJUMP $_exception_handler - -| int __cmpdf2(double, double); - FUNC(__cmpdf2) -SYM (__cmpdf2): - link a6,IMM (0) - pea 1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts - -|============================================================================= -| rounding routines -|============================================================================= - -| The rounding routines expect the number to be normalized in registers -| d0-d1-d2-d3, with the exponent in register d4. They assume that the -| exponent is larger or equal to 1. They return a properly normalized number -| if possible, and a denormalized number otherwise. The exponent is returned -| in d4. - -Lround$to$nearest: -| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"): -| Here we assume that the exponent is not too small (this should be checked -| before entering the rounding routine), but the number could be denormalized. - -| Check for denormalized numbers: -1: btst IMM (DBL_MANT_DIG-32),d0 - bne 2f | if set the number is normalized -| Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent -| is one (remember that a denormalized number corresponds to an -| exponent of -D_BIAS+1). -#ifndef __mcoldfire__ - cmpw IMM (1),d4 | remember that the exponent is at least one -#else - cmpl IMM (1),d4 | remember that the exponent is at least one -#endif - beq 2f | an exponent of one means denormalized - addl d3,d3 | else shift and adjust the exponent - addxl d2,d2 | - addxl d1,d1 | - addxl d0,d0 | -#ifndef __mcoldfire__ - dbra d4,1b | -#else - subql IMM (1), d4 - bpl 1b -#endif -2: -| Now round: we do it as follows: after the shifting we can write the -| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2. -| If delta < 1, do nothing. If delta > 1, add 1 to f. -| If delta == 1, we make sure the rounded number will be even (odd?) -| (after shifting). - btst IMM (0),d1 | is delta < 1? - beq 2f | if so, do not do anything - orl d2,d3 | is delta == 1? - bne 1f | if so round to even - movel d1,d3 | - andl IMM (2),d3 | bit 1 is the last significant bit - movel IMM (0),d2 | - addl d3,d1 | - addxl d2,d0 | - bra 2f | -1: movel IMM (1),d3 | else add 1 - movel IMM (0),d2 | - addl d3,d1 | - addxl d2,d0 -| Shift right once (because we used bit #DBL_MANT_DIG-32!). -2: -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 -#endif - -| Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a -| 'fraction overflow' ...). - btst IMM (DBL_MANT_DIG-32),d0 - beq 1f -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - addw IMM (1),d4 -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 - addl IMM (1),d4 -#endif -1: -| If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we -| have to put the exponent to zero and return a denormalized number. - btst IMM (DBL_MANT_DIG-32-1),d0 - beq 1f - jmp a0@ -1: movel IMM (0),d4 - jmp a0@ - -Lround$to$zero: -Lround$to$plus: -Lround$to$minus: - jmp a0@ -#endif /* L_double */ - -#ifdef L_float - - .globl SYM (_fpCCR) - .globl $_exception_handler - -QUIET_NaN = 0xffffffff -SIGNL_NaN = 0x7f800001 -INFINITY = 0x7f800000 - -F_MAX_EXP = 0xff -F_BIAS = 126 -FLT_MAX_EXP = F_MAX_EXP - F_BIAS -FLT_MIN_EXP = 1 - F_BIAS -FLT_MANT_DIG = 24 - -INEXACT_RESULT = 0x0001 -UNDERFLOW = 0x0002 -OVERFLOW = 0x0004 -DIVIDE_BY_ZERO = 0x0008 -INVALID_OPERATION = 0x0010 - -SINGLE_FLOAT = 1 - -NOOP = 0 -ADD = 1 -MULTIPLY = 2 -DIVIDE = 3 -NEGATE = 4 -COMPARE = 5 -EXTENDSFDF = 6 -TRUNCDFSF = 7 - -UNKNOWN = -1 -ROUND_TO_NEAREST = 0 | round result to nearest representable value -ROUND_TO_ZERO = 1 | round result towards zero -ROUND_TO_PLUS = 2 | round result towards plus infinity -ROUND_TO_MINUS = 3 | round result towards minus infinity - -| Entry points: - - .globl SYM (__addsf3) - .globl SYM (__subsf3) - .globl SYM (__mulsf3) - .globl SYM (__divsf3) - .globl SYM (__negsf2) - .globl SYM (__cmpsf2) - .globl SYM (__cmpsf2_internal) - .hidden SYM (__cmpsf2_internal) - -| These are common routines to return and signal exceptions. - - .text - .even - -Lf$den: -| Return and signal a denormalized number - orl d7,d0 - moveq IMM (INEXACT_RESULT+UNDERFLOW),d7 - moveq IMM (SINGLE_FLOAT),d6 - PICJUMP $_exception_handler - -Lf$infty: -Lf$overflow: -| Return a properly signed INFINITY and set the exception flags - movel IMM (INFINITY),d0 - orl d7,d0 - moveq IMM (INEXACT_RESULT+OVERFLOW),d7 - moveq IMM (SINGLE_FLOAT),d6 - PICJUMP $_exception_handler - -Lf$underflow: -| Return 0 and set the exception flags - moveq IMM (0),d0 - moveq IMM (INEXACT_RESULT+UNDERFLOW),d7 - moveq IMM (SINGLE_FLOAT),d6 - PICJUMP $_exception_handler - -Lf$inop: -| Return a quiet NaN and set the exception flags - movel IMM (QUIET_NaN),d0 - moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 - moveq IMM (SINGLE_FLOAT),d6 - PICJUMP $_exception_handler - -Lf$div$0: -| Return a properly signed INFINITY and set the exception flags - movel IMM (INFINITY),d0 - orl d7,d0 - moveq IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7 - moveq IMM (SINGLE_FLOAT),d6 - PICJUMP $_exception_handler - -|============================================================================= -|============================================================================= -| single precision routines -|============================================================================= -|============================================================================= - -| A single precision floating point number (float) has the format: -| -| struct _float { -| unsigned int sign : 1; /* sign bit */ -| unsigned int exponent : 8; /* exponent, shifted by 126 */ -| unsigned int fraction : 23; /* fraction */ -| } float; -| -| Thus sizeof(float) = 4 (32 bits). -| -| All the routines are callable from C programs, and return the result -| in the single register d0. They also preserve all registers except -| d0-d1 and a0-a1. - -|============================================================================= -| __subsf3 -|============================================================================= - -| float __subsf3(float, float); - FUNC(__subsf3) -SYM (__subsf3): - bchg IMM (31),sp@(8) | change sign of second operand - | and fall through -|============================================================================= -| __addsf3 -|============================================================================= - -| float __addsf3(float, float); - FUNC(__addsf3) -SYM (__addsf3): -#ifndef __mcoldfire__ - link a6,IMM (0) | everything will be done in registers - moveml d2-d7,sp@- | save all data registers but d0-d1 -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - movel a6@(8),d0 | get first operand - movel a6@(12),d1 | get second operand - movel d0,a0 | get d0's sign bit ' - addl d0,d0 | check and clear sign bit of a - beq Laddsf$b | if zero return second operand - movel d1,a1 | save b's sign bit ' - addl d1,d1 | get rid of sign bit - beq Laddsf$a | if zero return first operand - -| Get the exponents and check for denormalized and/or infinity. - - movel IMM (0x00ffffff),d4 | mask to get fraction - movel IMM (0x01000000),d5 | mask to put hidden bit back - - movel d0,d6 | save a to get exponent - andl d4,d0 | get fraction in d0 - notl d4 | make d4 into a mask for the exponent - andl d4,d6 | get exponent in d6 - beq Laddsf$a$den | branch if a is denormalized - cmpl d4,d6 | check for INFINITY or NaN - beq Laddsf$nf - swap d6 | put exponent into first word - orl d5,d0 | and put hidden bit back -Laddsf$1: -| Now we have a's exponent in d6 (second byte) and the mantissa in d0. ' - movel d1,d7 | get exponent in d7 - andl d4,d7 | - beq Laddsf$b$den | branch if b is denormalized - cmpl d4,d7 | check for INFINITY or NaN - beq Laddsf$nf - swap d7 | put exponent into first word - notl d4 | make d4 into a mask for the fraction - andl d4,d1 | get fraction in d1 - orl d5,d1 | and put hidden bit back -Laddsf$2: -| Now we have b's exponent in d7 (second byte) and the mantissa in d1. ' - -| Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we -| shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra -| bit). - - movel d1,d2 | move b to d2, since we want to use - | two registers to do the sum - movel IMM (0),d1 | and clear the new ones - movel d1,d3 | - -| Here we shift the numbers in registers d0 and d1 so the exponents are the -| same, and put the largest exponent in d6. Note that we are using two -| registers for each number (see the discussion by D. Knuth in "Seminumerical -| Algorithms"). -#ifndef __mcoldfire__ - cmpw d6,d7 | compare exponents -#else - cmpl d6,d7 | compare exponents -#endif - beq Laddsf$3 | if equal don't shift ' - bhi 5f | branch if second exponent largest -1: - subl d6,d7 | keep the largest exponent - negl d7 -#ifndef __mcoldfire__ - lsrw IMM (8),d7 | put difference in lower byte -#else - lsrl IMM (8),d7 | put difference in lower byte -#endif -| if difference is too large we don't shift (actually, we can just exit) ' -#ifndef __mcoldfire__ - cmpw IMM (FLT_MANT_DIG+2),d7 -#else - cmpl IMM (FLT_MANT_DIG+2),d7 -#endif - bge Laddsf$b$small -#ifndef __mcoldfire__ - cmpw IMM (16),d7 | if difference >= 16 swap -#else - cmpl IMM (16),d7 | if difference >= 16 swap -#endif - bge 4f -2: -#ifndef __mcoldfire__ - subw IMM (1),d7 -#else - subql IMM (1), d7 -#endif -3: -#ifndef __mcoldfire__ - lsrl IMM (1),d2 | shift right second operand - roxrl IMM (1),d3 - dbra d7,3b -#else - lsrl IMM (1),d3 - btst IMM (0),d2 - beq 10f - bset IMM (31),d3 -10: lsrl IMM (1),d2 - subql IMM (1), d7 - bpl 3b -#endif - bra Laddsf$3 -4: - movew d2,d3 - swap d3 - movew d3,d2 - swap d2 -#ifndef __mcoldfire__ - subw IMM (16),d7 -#else - subl IMM (16),d7 -#endif - bne 2b | if still more bits, go back to normal case - bra Laddsf$3 -5: -#ifndef __mcoldfire__ - exg d6,d7 | exchange the exponents -#else - eorl d6,d7 - eorl d7,d6 - eorl d6,d7 -#endif - subl d6,d7 | keep the largest exponent - negl d7 | -#ifndef __mcoldfire__ - lsrw IMM (8),d7 | put difference in lower byte -#else - lsrl IMM (8),d7 | put difference in lower byte -#endif -| if difference is too large we don't shift (and exit!) ' -#ifndef __mcoldfire__ - cmpw IMM (FLT_MANT_DIG+2),d7 -#else - cmpl IMM (FLT_MANT_DIG+2),d7 -#endif - bge Laddsf$a$small -#ifndef __mcoldfire__ - cmpw IMM (16),d7 | if difference >= 16 swap -#else - cmpl IMM (16),d7 | if difference >= 16 swap -#endif - bge 8f -6: -#ifndef __mcoldfire__ - subw IMM (1),d7 -#else - subl IMM (1),d7 -#endif -7: -#ifndef __mcoldfire__ - lsrl IMM (1),d0 | shift right first operand - roxrl IMM (1),d1 - dbra d7,7b -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 - subql IMM (1),d7 - bpl 7b -#endif - bra Laddsf$3 -8: - movew d0,d1 - swap d1 - movew d1,d0 - swap d0 -#ifndef __mcoldfire__ - subw IMM (16),d7 -#else - subl IMM (16),d7 -#endif - bne 6b | if still more bits, go back to normal case - | otherwise we fall through - -| Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the -| signs are stored in a0 and a1). - -Laddsf$3: -| Here we have to decide whether to add or subtract the numbers -#ifndef __mcoldfire__ - exg d6,a0 | get signs back - exg d7,a1 | and save the exponents -#else - movel d6,d4 - movel a0,d6 - movel d4,a0 - movel d7,d4 - movel a1,d7 - movel d4,a1 -#endif - eorl d6,d7 | combine sign bits - bmi Lsubsf$0 | if negative a and b have opposite - | sign so we actually subtract the - | numbers - -| Here we have both positive or both negative -#ifndef __mcoldfire__ - exg d6,a0 | now we have the exponent in d6 -#else - movel d6,d4 - movel a0,d6 - movel d4,a0 -#endif - movel a0,d7 | and sign in d7 - andl IMM (0x80000000),d7 -| Here we do the addition. - addl d3,d1 - addxl d2,d0 -| Note: now we have d2, d3, d4 and d5 to play with! - -| Put the exponent, in the first byte, in d2, to use the "standard" rounding -| routines: - movel d6,d2 -#ifndef __mcoldfire__ - lsrw IMM (8),d2 -#else - lsrl IMM (8),d2 -#endif - -| Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider -| the case of denormalized numbers in the rounding routine itself). -| As in the addition (not in the subtraction!) we could have set -| one more bit we check this: - btst IMM (FLT_MANT_DIG+1),d0 - beq 1f -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 -#endif - addl IMM (1),d2 -1: - lea pc@(Laddsf$4),a0 | to return from rounding routine - PICLEA SYM (_fpCCR),a1 | check the rounding mode -#ifdef __mcoldfire__ - clrl d6 -#endif - movew a1@(6),d6 | rounding mode in d6 - beq Lround$to$nearest -#ifndef __mcoldfire__ - cmpw IMM (ROUND_TO_PLUS),d6 -#else - cmpl IMM (ROUND_TO_PLUS),d6 -#endif - bhi Lround$to$minus - blt Lround$to$zero - bra Lround$to$plus -Laddsf$4: -| Put back the exponent, but check for overflow. -#ifndef __mcoldfire__ - cmpw IMM (0xff),d2 -#else - cmpl IMM (0xff),d2 -#endif - bhi 1f - bclr IMM (FLT_MANT_DIG-1),d0 -#ifndef __mcoldfire__ - lslw IMM (7),d2 -#else - lsll IMM (7),d2 -#endif - swap d2 - orl d2,d0 - bra Laddsf$ret -1: - moveq IMM (ADD),d5 - bra Lf$overflow - -Lsubsf$0: -| We are here if a > 0 and b < 0 (sign bits cleared). -| Here we do the subtraction. - movel d6,d7 | put sign in d7 - andl IMM (0x80000000),d7 - - subl d3,d1 | result in d0-d1 - subxl d2,d0 | - beq Laddsf$ret | if zero just exit - bpl 1f | if positive skip the following - bchg IMM (31),d7 | change sign bit in d7 - negl d1 - negxl d0 -1: -#ifndef __mcoldfire__ - exg d2,a0 | now we have the exponent in d2 - lsrw IMM (8),d2 | put it in the first byte -#else - movel d2,d4 - movel a0,d2 - movel d4,a0 - lsrl IMM (8),d2 | put it in the first byte -#endif - -| Now d0-d1 is positive and the sign bit is in d7. - -| Note that we do not have to normalize, since in the subtraction bit -| #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by -| the rounding routines themselves. - lea pc@(Lsubsf$1),a0 | to return from rounding routine - PICLEA SYM (_fpCCR),a1 | check the rounding mode -#ifdef __mcoldfire__ - clrl d6 -#endif - movew a1@(6),d6 | rounding mode in d6 - beq Lround$to$nearest -#ifndef __mcoldfire__ - cmpw IMM (ROUND_TO_PLUS),d6 -#else - cmpl IMM (ROUND_TO_PLUS),d6 -#endif - bhi Lround$to$minus - blt Lround$to$zero - bra Lround$to$plus -Lsubsf$1: -| Put back the exponent (we can't have overflow!). ' - bclr IMM (FLT_MANT_DIG-1),d0 -#ifndef __mcoldfire__ - lslw IMM (7),d2 -#else - lsll IMM (7),d2 -#endif - swap d2 - orl d2,d0 - bra Laddsf$ret - -| If one of the numbers was too small (difference of exponents >= -| FLT_MANT_DIG+2) we return the other (and now we don't have to ' -| check for finiteness or zero). -Laddsf$a$small: - movel a6@(12),d0 - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | restore data registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | and return - rts - -Laddsf$b$small: - movel a6@(8),d0 - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | restore data registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | and return - rts - -| If the numbers are denormalized remember to put exponent equal to 1. - -Laddsf$a$den: - movel d5,d6 | d5 contains 0x01000000 - swap d6 - bra Laddsf$1 - -Laddsf$b$den: - movel d5,d7 - swap d7 - notl d4 | make d4 into a mask for the fraction - | (this was not executed after the jump) - bra Laddsf$2 - -| The rest is mainly code for the different results which can be -| returned (checking always for +/-INFINITY and NaN). - -Laddsf$b: -| Return b (if a is zero). - movel a6@(12),d0 - cmpl IMM (0x80000000),d0 | Check if b is -0 - bne 1f - movel a0,d7 - andl IMM (0x80000000),d7 | Use the sign of a - clrl d0 - bra Laddsf$ret -Laddsf$a: -| Return a (if b is zero). - movel a6@(8),d0 -1: - moveq IMM (ADD),d5 -| We have to check for NaN and +/-infty. - movel d0,d7 - andl IMM (0x80000000),d7 | put sign in d7 - bclr IMM (31),d0 | clear sign - cmpl IMM (INFINITY),d0 | check for infty or NaN - bge 2f - movel d0,d0 | check for zero (we do this because we don't ' - bne Laddsf$ret | want to return -0 by mistake - bclr IMM (31),d7 | if zero be sure to clear sign - bra Laddsf$ret | if everything OK just return -2: -| The value to be returned is either +/-infty or NaN - andl IMM (0x007fffff),d0 | check for NaN - bne Lf$inop | if mantissa not zero is NaN - bra Lf$infty - -Laddsf$ret: -| Normal exit (a and b nonzero, result is not NaN nor +/-infty). -| We have to clear the exception flags (just the exception type). - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ - orl d7,d0 | put sign bit -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | restore data registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | and return - rts - -Laddsf$ret$den: -| Return a denormalized number (for addition we don't signal underflow) ' - lsrl IMM (1),d0 | remember to shift right back once - bra Laddsf$ret | and return - -| Note: when adding two floats of the same sign if either one is -| NaN we return NaN without regard to whether the other is finite or -| not. When subtracting them (i.e., when adding two numbers of -| opposite signs) things are more complicated: if both are INFINITY -| we return NaN, if only one is INFINITY and the other is NaN we return -| NaN, but if it is finite we return INFINITY with the corresponding sign. - -Laddsf$nf: - moveq IMM (ADD),d5 -| This could be faster but it is not worth the effort, since it is not -| executed very often. We sacrifice speed for clarity here. - movel a6@(8),d0 | get the numbers back (remember that we - movel a6@(12),d1 | did some processing already) - movel IMM (INFINITY),d4 | useful constant (INFINITY) - movel d0,d2 | save sign bits - movel d1,d3 - bclr IMM (31),d0 | clear sign bits - bclr IMM (31),d1 -| We know that one of them is either NaN of +/-INFINITY -| Check for NaN (if either one is NaN return NaN) - cmpl d4,d0 | check first a (d0) - bhi Lf$inop - cmpl d4,d1 | check now b (d1) - bhi Lf$inop -| Now comes the check for +/-INFINITY. We know that both are (maybe not -| finite) numbers, but we have to check if both are infinite whether we -| are adding or subtracting them. - eorl d3,d2 | to check sign bits - bmi 1f - movel d0,d7 - andl IMM (0x80000000),d7 | get (common) sign bit - bra Lf$infty -1: -| We know one (or both) are infinite, so we test for equality between the -| two numbers (if they are equal they have to be infinite both, so we -| return NaN). - cmpl d1,d0 | are both infinite? - beq Lf$inop | if so return NaN - - movel d0,d7 - andl IMM (0x80000000),d7 | get a's sign bit ' - cmpl d4,d0 | test now for infinity - beq Lf$infty | if a is INFINITY return with this sign - bchg IMM (31),d7 | else we know b is INFINITY and has - bra Lf$infty | the opposite sign - -|============================================================================= -| __mulsf3 -|============================================================================= - -| float __mulsf3(float, float); - FUNC(__mulsf3) -SYM (__mulsf3): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - movel a6@(8),d0 | get a into d0 - movel a6@(12),d1 | and b into d1 - movel d0,d7 | d7 will hold the sign of the product - eorl d1,d7 | - andl IMM (0x80000000),d7 - movel IMM (INFINITY),d6 | useful constant (+INFINITY) - movel d6,d5 | another (mask for fraction) - notl d5 | - movel IMM (0x00800000),d4 | this is to put hidden bit back - bclr IMM (31),d0 | get rid of a's sign bit ' - movel d0,d2 | - beq Lmulsf$a$0 | branch if a is zero - bclr IMM (31),d1 | get rid of b's sign bit ' - movel d1,d3 | - beq Lmulsf$b$0 | branch if b is zero - cmpl d6,d0 | is a big? - bhi Lmulsf$inop | if a is NaN return NaN - beq Lmulsf$inf | if a is INFINITY we have to check b - cmpl d6,d1 | now compare b with INFINITY - bhi Lmulsf$inop | is b NaN? - beq Lmulsf$overflow | is b INFINITY? -| Here we have both numbers finite and nonzero (and with no sign bit). -| Now we get the exponents into d2 and d3. - andl d6,d2 | and isolate exponent in d2 - beq Lmulsf$a$den | if exponent is zero we have a denormalized - andl d5,d0 | and isolate fraction - orl d4,d0 | and put hidden bit back - swap d2 | I like exponents in the first byte -#ifndef __mcoldfire__ - lsrw IMM (7),d2 | -#else - lsrl IMM (7),d2 | -#endif -Lmulsf$1: | number - andl d6,d3 | - beq Lmulsf$b$den | - andl d5,d1 | - orl d4,d1 | - swap d3 | -#ifndef __mcoldfire__ - lsrw IMM (7),d3 | -#else - lsrl IMM (7),d3 | -#endif -Lmulsf$2: | -#ifndef __mcoldfire__ - addw d3,d2 | add exponents - subw IMM (F_BIAS+1),d2 | and subtract bias (plus one) -#else - addl d3,d2 | add exponents - subl IMM (F_BIAS+1),d2 | and subtract bias (plus one) -#endif - -| We are now ready to do the multiplication. The situation is as follows: -| both a and b have bit FLT_MANT_DIG-1 set (even if they were -| denormalized to start with!), which means that in the product -| bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the -| high long) is set. - -| To do the multiplication let us move the number a little bit around ... - movel d1,d6 | second operand in d6 - movel d0,d5 | first operand in d4-d5 - movel IMM (0),d4 - movel d4,d1 | the sums will go in d0-d1 - movel d4,d0 - -| now bit FLT_MANT_DIG-1 becomes bit 31: - lsll IMM (31-FLT_MANT_DIG+1),d6 - -| Start the loop (we loop #FLT_MANT_DIG times): - moveq IMM (FLT_MANT_DIG-1),d3 -1: addl d1,d1 | shift sum - addxl d0,d0 - lsll IMM (1),d6 | get bit bn - bcc 2f | if not set skip sum - addl d5,d1 | add a - addxl d4,d0 -2: -#ifndef __mcoldfire__ - dbf d3,1b | loop back -#else - subql IMM (1),d3 - bpl 1b -#endif - -| Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG -| (mod 32) of d0 set. The first thing to do now is to normalize it so bit -| FLT_MANT_DIG is set (to do the rounding). -#ifndef __mcoldfire__ - rorl IMM (6),d1 - swap d1 - movew d1,d3 - andw IMM (0x03ff),d3 - andw IMM (0xfd00),d1 -#else - movel d1,d3 - lsll IMM (8),d1 - addl d1,d1 - addl d1,d1 - moveq IMM (22),d5 - lsrl d5,d3 - orl d3,d1 - andl IMM (0xfffffd00),d1 -#endif - lsll IMM (8),d0 - addl d0,d0 - addl d0,d0 -#ifndef __mcoldfire__ - orw d3,d0 -#else - orl d3,d0 -#endif - - moveq IMM (MULTIPLY),d5 - - btst IMM (FLT_MANT_DIG+1),d0 - beq Lround$exit -#ifndef __mcoldfire__ - lsrl IMM (1),d0 - roxrl IMM (1),d1 - addw IMM (1),d2 -#else - lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 - addql IMM (1),d2 -#endif - bra Lround$exit - -Lmulsf$inop: - moveq IMM (MULTIPLY),d5 - bra Lf$inop - -Lmulsf$overflow: - moveq IMM (MULTIPLY),d5 - bra Lf$overflow - -Lmulsf$inf: - moveq IMM (MULTIPLY),d5 -| If either is NaN return NaN; else both are (maybe infinite) numbers, so -| return INFINITY with the correct sign (which is in d7). - cmpl d6,d1 | is b NaN? - bhi Lf$inop | if so return NaN - bra Lf$overflow | else return +/-INFINITY - -| If either number is zero return zero, unless the other is +/-INFINITY, -| or NaN, in which case we return NaN. -Lmulsf$b$0: -| Here d1 (==b) is zero. - movel a6@(8),d1 | get a again to check for non-finiteness - bra 1f -Lmulsf$a$0: - movel a6@(12),d1 | get b again to check for non-finiteness -1: bclr IMM (31),d1 | clear sign bit - cmpl IMM (INFINITY),d1 | and check for a large exponent - bge Lf$inop | if b is +/-INFINITY or NaN return NaN - movel d7,d0 | else return signed zero - PICLEA SYM (_fpCCR),a0 | - movew IMM (0),a0@ | -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | - rts | - -| If a number is denormalized we put an exponent of 1 but do not put the -| hidden bit back into the fraction; instead we shift left until bit 23 -| (the hidden bit) is set, adjusting the exponent accordingly. We do this -| to ensure that the product of the fractions is close to 1. -Lmulsf$a$den: - movel IMM (1),d2 - andl d5,d0 -1: addl d0,d0 | shift a left (until bit 23 is set) -#ifndef __mcoldfire__ - subw IMM (1),d2 | and adjust exponent -#else - subql IMM (1),d2 | and adjust exponent -#endif - btst IMM (FLT_MANT_DIG-1),d0 - bne Lmulsf$1 | - bra 1b | else loop back - -Lmulsf$b$den: - movel IMM (1),d3 - andl d5,d1 -1: addl d1,d1 | shift b left until bit 23 is set -#ifndef __mcoldfire__ - subw IMM (1),d3 | and adjust exponent -#else - subql IMM (1),d3 | and adjust exponent -#endif - btst IMM (FLT_MANT_DIG-1),d1 - bne Lmulsf$2 | - bra 1b | else loop back - -|============================================================================= -| __divsf3 -|============================================================================= - -| float __divsf3(float, float); - FUNC(__divsf3) -SYM (__divsf3): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - movel a6@(8),d0 | get a into d0 - movel a6@(12),d1 | and b into d1 - movel d0,d7 | d7 will hold the sign of the result - eorl d1,d7 | - andl IMM (0x80000000),d7 | - movel IMM (INFINITY),d6 | useful constant (+INFINITY) - movel d6,d5 | another (mask for fraction) - notl d5 | - movel IMM (0x00800000),d4 | this is to put hidden bit back - bclr IMM (31),d0 | get rid of a's sign bit ' - movel d0,d2 | - beq Ldivsf$a$0 | branch if a is zero - bclr IMM (31),d1 | get rid of b's sign bit ' - movel d1,d3 | - beq Ldivsf$b$0 | branch if b is zero - cmpl d6,d0 | is a big? - bhi Ldivsf$inop | if a is NaN return NaN - beq Ldivsf$inf | if a is INFINITY we have to check b - cmpl d6,d1 | now compare b with INFINITY - bhi Ldivsf$inop | if b is NaN return NaN - beq Ldivsf$underflow -| Here we have both numbers finite and nonzero (and with no sign bit). -| Now we get the exponents into d2 and d3 and normalize the numbers to -| ensure that the ratio of the fractions is close to 1. We do this by -| making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set. - andl d6,d2 | and isolate exponent in d2 - beq Ldivsf$a$den | if exponent is zero we have a denormalized - andl d5,d0 | and isolate fraction - orl d4,d0 | and put hidden bit back - swap d2 | I like exponents in the first byte -#ifndef __mcoldfire__ - lsrw IMM (7),d2 | -#else - lsrl IMM (7),d2 | -#endif -Ldivsf$1: | - andl d6,d3 | - beq Ldivsf$b$den | - andl d5,d1 | - orl d4,d1 | - swap d3 | -#ifndef __mcoldfire__ - lsrw IMM (7),d3 | -#else - lsrl IMM (7),d3 | -#endif -Ldivsf$2: | -#ifndef __mcoldfire__ - subw d3,d2 | subtract exponents - addw IMM (F_BIAS),d2 | and add bias -#else - subl d3,d2 | subtract exponents - addl IMM (F_BIAS),d2 | and add bias -#endif - -| We are now ready to do the division. We have prepared things in such a way -| that the ratio of the fractions will be less than 2 but greater than 1/2. -| At this point the registers in use are: -| d0 holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1) -| d1 holds b (second operand, bit FLT_MANT_DIG=1) -| d2 holds the difference of the exponents, corrected by the bias -| d7 holds the sign of the ratio -| d4, d5, d6 hold some constants - movel d7,a0 | d6-d7 will hold the ratio of the fractions - movel IMM (0),d6 | - movel d6,d7 - - moveq IMM (FLT_MANT_DIG+1),d3 -1: cmpl d0,d1 | is a < b? - bhi 2f | - bset d3,d6 | set a bit in d6 - subl d1,d0 | if a >= b a <-- a-b - beq 3f | if a is zero, exit -2: addl d0,d0 | multiply a by 2 -#ifndef __mcoldfire__ - dbra d3,1b -#else - subql IMM (1),d3 - bpl 1b -#endif - -| Now we keep going to set the sticky bit ... - moveq IMM (FLT_MANT_DIG),d3 -1: cmpl d0,d1 - ble 2f - addl d0,d0 -#ifndef __mcoldfire__ - dbra d3,1b -#else - subql IMM(1),d3 - bpl 1b -#endif - movel IMM (0),d1 - bra 3f -2: movel IMM (0),d1 -#ifndef __mcoldfire__ - subw IMM (FLT_MANT_DIG),d3 - addw IMM (31),d3 -#else - subl IMM (FLT_MANT_DIG),d3 - addl IMM (31),d3 -#endif - bset d3,d1 -3: - movel d6,d0 | put the ratio in d0-d1 - movel a0,d7 | get sign back - -| Because of the normalization we did before we are guaranteed that -| d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set, -| bit 25 could be set, and if it is not set then bit 24 is necessarily set. - btst IMM (FLT_MANT_DIG+1),d0 - beq 1f | if it is not set, then bit 24 is set - lsrl IMM (1),d0 | -#ifndef __mcoldfire__ - addw IMM (1),d2 | -#else - addl IMM (1),d2 | -#endif -1: -| Now round, check for over- and underflow, and exit. - moveq IMM (DIVIDE),d5 - bra Lround$exit - -Ldivsf$inop: - moveq IMM (DIVIDE),d5 - bra Lf$inop - -Ldivsf$overflow: - moveq IMM (DIVIDE),d5 - bra Lf$overflow - -Ldivsf$underflow: - moveq IMM (DIVIDE),d5 - bra Lf$underflow - -Ldivsf$a$0: - moveq IMM (DIVIDE),d5 -| If a is zero check to see whether b is zero also. In that case return -| NaN; then check if b is NaN, and return NaN also in that case. Else -| return a properly signed zero. - andl IMM (0x7fffffff),d1 | clear sign bit and test b - beq Lf$inop | if b is also zero return NaN - cmpl IMM (INFINITY),d1 | check for NaN - bhi Lf$inop | - movel d7,d0 | else return signed zero - PICLEA SYM (_fpCCR),a0 | - movew IMM (0),a0@ | -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | -#else - moveml sp@,d2-d7 | - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 | - rts | - -Ldivsf$b$0: - moveq IMM (DIVIDE),d5 -| If we got here a is not zero. Check if a is NaN; in that case return NaN, -| else return +/-INFINITY. Remember that a is in d0 with the sign bit -| cleared already. - cmpl IMM (INFINITY),d0 | compare d0 with INFINITY - bhi Lf$inop | if larger it is NaN - bra Lf$div$0 | else signal DIVIDE_BY_ZERO - -Ldivsf$inf: - moveq IMM (DIVIDE),d5 -| If a is INFINITY we have to check b - cmpl IMM (INFINITY),d1 | compare b with INFINITY - bge Lf$inop | if b is NaN or INFINITY return NaN - bra Lf$overflow | else return overflow - -| If a number is denormalized we put an exponent of 1 but do not put the -| bit back into the fraction. -Ldivsf$a$den: - movel IMM (1),d2 - andl d5,d0 -1: addl d0,d0 | shift a left until bit FLT_MANT_DIG-1 is set -#ifndef __mcoldfire__ - subw IMM (1),d2 | and adjust exponent -#else - subl IMM (1),d2 | and adjust exponent -#endif - btst IMM (FLT_MANT_DIG-1),d0 - bne Ldivsf$1 - bra 1b - -Ldivsf$b$den: - movel IMM (1),d3 - andl d5,d1 -1: addl d1,d1 | shift b left until bit FLT_MANT_DIG is set -#ifndef __mcoldfire__ - subw IMM (1),d3 | and adjust exponent -#else - subl IMM (1),d3 | and adjust exponent -#endif - btst IMM (FLT_MANT_DIG-1),d1 - bne Ldivsf$2 - bra 1b - -Lround$exit: -| This is a common exit point for __mulsf3 and __divsf3. - -| First check for underlow in the exponent: -#ifndef __mcoldfire__ - cmpw IMM (-FLT_MANT_DIG-1),d2 -#else - cmpl IMM (-FLT_MANT_DIG-1),d2 -#endif - blt Lf$underflow -| It could happen that the exponent is less than 1, in which case the -| number is denormalized. In this case we shift right and adjust the -| exponent until it becomes 1 or the fraction is zero (in the latter case -| we signal underflow and return zero). - movel IMM (0),d6 | d6 is used temporarily -#ifndef __mcoldfire__ - cmpw IMM (1),d2 | if the exponent is less than 1 we -#else - cmpl IMM (1),d2 | if the exponent is less than 1 we -#endif - bge 2f | have to shift right (denormalize) -1: -#ifndef __mcoldfire__ - addw IMM (1),d2 | adjust the exponent - lsrl IMM (1),d0 | shift right once - roxrl IMM (1),d1 | - roxrl IMM (1),d6 | d6 collect bits we would lose otherwise - cmpw IMM (1),d2 | is the exponent 1 already? -#else - addql IMM (1),d2 | adjust the exponent - lsrl IMM (1),d6 - btst IMM (0),d1 - beq 11f - bset IMM (31),d6 -11: lsrl IMM (1),d1 - btst IMM (0),d0 - beq 10f - bset IMM (31),d1 -10: lsrl IMM (1),d0 - cmpl IMM (1),d2 | is the exponent 1 already? -#endif - beq 2f | if not loop back - bra 1b | - bra Lf$underflow | safety check, shouldn't execute ' -2: orl d6,d1 | this is a trick so we don't lose ' - | the extra bits which were flushed right -| Now call the rounding routine (which takes care of denormalized numbers): - lea pc@(Lround$0),a0 | to return from rounding routine - PICLEA SYM (_fpCCR),a1 | check the rounding mode -#ifdef __mcoldfire__ - clrl d6 -#endif - movew a1@(6),d6 | rounding mode in d6 - beq Lround$to$nearest -#ifndef __mcoldfire__ - cmpw IMM (ROUND_TO_PLUS),d6 -#else - cmpl IMM (ROUND_TO_PLUS),d6 -#endif - bhi Lround$to$minus - blt Lround$to$zero - bra Lround$to$plus -Lround$0: -| Here we have a correctly rounded result (either normalized or denormalized). - -| Here we should have either a normalized number or a denormalized one, and -| the exponent is necessarily larger or equal to 1 (so we don't have to ' -| check again for underflow!). We have to check for overflow or for a -| denormalized number (which also signals underflow). -| Check for overflow (i.e., exponent >= 255). -#ifndef __mcoldfire__ - cmpw IMM (0x00ff),d2 -#else - cmpl IMM (0x00ff),d2 -#endif - bge Lf$overflow -| Now check for a denormalized number (exponent==0). - movew d2,d2 - beq Lf$den -1: -| Put back the exponents and sign and return. -#ifndef __mcoldfire__ - lslw IMM (7),d2 | exponent back to fourth byte -#else - lsll IMM (7),d2 | exponent back to fourth byte -#endif - bclr IMM (FLT_MANT_DIG-1),d0 - swap d0 | and put back exponent -#ifndef __mcoldfire__ - orw d2,d0 | -#else - orl d2,d0 -#endif - swap d0 | - orl d7,d0 | and sign also - - PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts - -|============================================================================= -| __negsf2 -|============================================================================= - -| This is trivial and could be shorter if we didn't bother checking for NaN ' -| and +/-INFINITY. - -| float __negsf2(float); - FUNC(__negsf2) -SYM (__negsf2): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - moveq IMM (NEGATE),d5 - movel a6@(8),d0 | get number to negate in d0 - bchg IMM (31),d0 | negate - movel d0,d1 | make a positive copy - bclr IMM (31),d1 | - tstl d1 | check for zero - beq 2f | if zero (either sign) return +zero - cmpl IMM (INFINITY),d1 | compare to +INFINITY - blt 1f | - bhi Lf$inop | if larger (fraction not zero) is NaN - movel d0,d7 | else get sign and return INFINITY - andl IMM (0x80000000),d7 - bra Lf$infty -1: PICLEA SYM (_fpCCR),a0 - movew IMM (0),a0@ -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts -2: bclr IMM (31),d0 - bra 1b - -|============================================================================= -| __cmpsf2 -|============================================================================= - -GREATER = 1 -LESS = -1 -EQUAL = 0 - -| int __cmpsf2_internal(float, float, int); -SYM (__cmpsf2_internal): -#ifndef __mcoldfire__ - link a6,IMM (0) - moveml d2-d7,sp@- | save registers -#else - link a6,IMM (-24) - moveml d2-d7,sp@ -#endif - moveq IMM (COMPARE),d5 - movel a6@(8),d0 | get first operand - movel a6@(12),d1 | get second operand -| Check if either is NaN, and in that case return garbage and signal -| INVALID_OPERATION. Check also if either is zero, and clear the signs -| if necessary. - movel d0,d6 - andl IMM (0x7fffffff),d0 - beq Lcmpsf$a$0 - cmpl IMM (0x7f800000),d0 - bhi Lcmpf$inop -Lcmpsf$1: - movel d1,d7 - andl IMM (0x7fffffff),d1 - beq Lcmpsf$b$0 - cmpl IMM (0x7f800000),d1 - bhi Lcmpf$inop -Lcmpsf$2: -| Check the signs - eorl d6,d7 - bpl 1f -| If the signs are not equal check if a >= 0 - tstl d6 - bpl Lcmpsf$a$gt$b | if (a >= 0 && b < 0) => a > b - bmi Lcmpsf$b$gt$a | if (a < 0 && b >= 0) => a < b -1: -| If the signs are equal check for < 0 - tstl d6 - bpl 1f -| If both are negative exchange them -#ifndef __mcoldfire__ - exg d0,d1 -#else - movel d0,d7 - movel d1,d0 - movel d7,d1 -#endif -1: -| Now that they are positive we just compare them as longs (does this also -| work for denormalized numbers?). - cmpl d0,d1 - bhi Lcmpsf$b$gt$a | |b| > |a| - bne Lcmpsf$a$gt$b | |b| < |a| -| If we got here a == b. - movel IMM (EQUAL),d0 -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | put back the registers -#else - moveml sp@,d2-d7 -#endif - unlk a6 - rts -Lcmpsf$a$gt$b: - movel IMM (GREATER),d0 -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | put back the registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts -Lcmpsf$b$gt$a: - movel IMM (LESS),d0 -#ifndef __mcoldfire__ - moveml sp@+,d2-d7 | put back the registers -#else - moveml sp@,d2-d7 - | XXX if frame pointer is ever removed, stack pointer must - | be adjusted here. -#endif - unlk a6 - rts - -Lcmpsf$a$0: - bclr IMM (31),d6 - bra Lcmpsf$1 -Lcmpsf$b$0: - bclr IMM (31),d7 - bra Lcmpsf$2 - -Lcmpf$inop: - movl a6@(16),d0 - moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 - moveq IMM (SINGLE_FLOAT),d6 - PICJUMP $_exception_handler - -| int __cmpsf2(float, float); - FUNC(__cmpsf2) -SYM (__cmpsf2): - link a6,IMM (0) - pea 1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts - -|============================================================================= -| rounding routines -|============================================================================= - -| The rounding routines expect the number to be normalized in registers -| d0-d1, with the exponent in register d2. They assume that the -| exponent is larger or equal to 1. They return a properly normalized number -| if possible, and a denormalized number otherwise. The exponent is returned -| in d2. - -Lround$to$nearest: -| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"): -| Here we assume that the exponent is not too small (this should be checked -| before entering the rounding routine), but the number could be denormalized. - -| Check for denormalized numbers: -1: btst IMM (FLT_MANT_DIG),d0 - bne 2f | if set the number is normalized -| Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent -| is one (remember that a denormalized number corresponds to an -| exponent of -F_BIAS+1). -#ifndef __mcoldfire__ - cmpw IMM (1),d2 | remember that the exponent is at least one -#else - cmpl IMM (1),d2 | remember that the exponent is at least one -#endif - beq 2f | an exponent of one means denormalized - addl d1,d1 | else shift and adjust the exponent - addxl d0,d0 | -#ifndef __mcoldfire__ - dbra d2,1b | -#else - subql IMM (1),d2 - bpl 1b -#endif -2: -| Now round: we do it as follows: after the shifting we can write the -| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2. -| If delta < 1, do nothing. If delta > 1, add 1 to f. -| If delta == 1, we make sure the rounded number will be even (odd?) -| (after shifting). - btst IMM (0),d0 | is delta < 1? - beq 2f | if so, do not do anything - tstl d1 | is delta == 1? - bne 1f | if so round to even - movel d0,d1 | - andl IMM (2),d1 | bit 1 is the last significant bit - addl d1,d0 | - bra 2f | -1: movel IMM (1),d1 | else add 1 - addl d1,d0 | -| Shift right once (because we used bit #FLT_MANT_DIG!). -2: lsrl IMM (1),d0 -| Now check again bit #FLT_MANT_DIG (rounding could have produced a -| 'fraction overflow' ...). - btst IMM (FLT_MANT_DIG),d0 - beq 1f - lsrl IMM (1),d0 -#ifndef __mcoldfire__ - addw IMM (1),d2 -#else - addql IMM (1),d2 -#endif -1: -| If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we -| have to put the exponent to zero and return a denormalized number. - btst IMM (FLT_MANT_DIG-1),d0 - beq 1f - jmp a0@ -1: movel IMM (0),d2 - jmp a0@ - -Lround$to$zero: -Lround$to$plus: -Lround$to$minus: - jmp a0@ -#endif /* L_float */ - -| gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2, -| __ledf2, __ltdf2 to all return the same value as a direct call to -| __cmpdf2 would. In this implementation, each of these routines -| simply calls __cmpdf2. It would be more efficient to give the -| __cmpdf2 routine several names, but separating them out will make it -| easier to write efficient versions of these routines someday. -| If the operands recompare unordered unordered __gtdf2 and __gedf2 return -1. -| The other routines return 1. - -#ifdef L_eqdf2 - .text - FUNC(__eqdf2) - .globl SYM (__eqdf2) -SYM (__eqdf2): - link a6,IMM (0) - pea 1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts -#endif /* L_eqdf2 */ - -#ifdef L_nedf2 - .text - FUNC(__nedf2) - .globl SYM (__nedf2) -SYM (__nedf2): - link a6,IMM (0) - pea 1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts -#endif /* L_nedf2 */ - -#ifdef L_gtdf2 - .text - FUNC(__gtdf2) - .globl SYM (__gtdf2) -SYM (__gtdf2): - link a6,IMM (0) - pea -1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts -#endif /* L_gtdf2 */ - -#ifdef L_gedf2 - .text - FUNC(__gedf2) - .globl SYM (__gedf2) -SYM (__gedf2): - link a6,IMM (0) - pea -1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts -#endif /* L_gedf2 */ - -#ifdef L_ltdf2 - .text - FUNC(__ltdf2) - .globl SYM (__ltdf2) -SYM (__ltdf2): - link a6,IMM (0) - pea 1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts -#endif /* L_ltdf2 */ - -#ifdef L_ledf2 - .text - FUNC(__ledf2) - .globl SYM (__ledf2) -SYM (__ledf2): - link a6,IMM (0) - pea 1 - movl a6@(20),sp@- - movl a6@(16),sp@- - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpdf2_internal) - unlk a6 - rts -#endif /* L_ledf2 */ - -| The comments above about __eqdf2, et. al., also apply to __eqsf2, -| et. al., except that the latter call __cmpsf2 rather than __cmpdf2. - -#ifdef L_eqsf2 - .text - FUNC(__eqsf2) - .globl SYM (__eqsf2) -SYM (__eqsf2): - link a6,IMM (0) - pea 1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts -#endif /* L_eqsf2 */ - -#ifdef L_nesf2 - .text - FUNC(__nesf2) - .globl SYM (__nesf2) -SYM (__nesf2): - link a6,IMM (0) - pea 1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts -#endif /* L_nesf2 */ - -#ifdef L_gtsf2 - .text - FUNC(__gtsf2) - .globl SYM (__gtsf2) -SYM (__gtsf2): - link a6,IMM (0) - pea -1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts -#endif /* L_gtsf2 */ - -#ifdef L_gesf2 - .text - FUNC(__gesf2) - .globl SYM (__gesf2) -SYM (__gesf2): - link a6,IMM (0) - pea -1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts -#endif /* L_gesf2 */ - -#ifdef L_ltsf2 - .text - FUNC(__ltsf2) - .globl SYM (__ltsf2) -SYM (__ltsf2): - link a6,IMM (0) - pea 1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts -#endif /* L_ltsf2 */ - -#ifdef L_lesf2 - .text - FUNC(__lesf2) - .globl SYM (__lesf2) -SYM (__lesf2): - link a6,IMM (0) - pea 1 - movl a6@(12),sp@- - movl a6@(8),sp@- - PICCALL SYM (__cmpsf2_internal) - unlk a6 - rts -#endif /* L_lesf2 */ - -#if defined (__ELF__) && defined (__linux__) - /* Make stack non-executable for ELF linux targets. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/gcc/config/m68k/t-crtstuff b/gcc/config/m68k/t-crtstuff deleted file mode 100644 index a8bdb502d66..00000000000 --- a/gcc/config/m68k/t-crtstuff +++ /dev/null @@ -1,10 +0,0 @@ -EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crti.o crtn.o - -# Add flags here as required. -CRTSTUFF_T_CFLAGS = - -# Assemble startup files. -$(T)crti.o: $(srcdir)/config/m68k/crti.s $(GCC_PASSES) - $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o $(srcdir)/config/m68k/crti.s -$(T)crtn.o: $(srcdir)/config/m68k/crtn.s $(GCC_PASSES) - $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o $(srcdir)/config/m68k/crtn.s diff --git a/gcc/config/m68k/t-floatlib b/gcc/config/m68k/t-floatlib deleted file mode 100644 index 2039d1d0dc4..00000000000 --- a/gcc/config/m68k/t-floatlib +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2007 Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -LIB1ASMSRC = m68k/lb1sf68.asm -LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \ - _double _float _floatex \ - _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \ - _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2 - -LIB2FUNCS_EXTRA = fpgnulib.c xfgnulib.c - -fpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c - cp $(srcdir)/config/m68k/fpgnulib.c fpgnulib.c -xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define EXTFLOAT' > xfgnulib.c - cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c diff --git a/gcc/config/m68k/t-linux b/gcc/config/m68k/t-linux index a8cb563a2e2..3fa29474693 100644 --- a/gcc/config/m68k/t-linux +++ b/gcc/config/m68k/t-linux @@ -1,4 +1,4 @@ -# Copyright (C) 2008, 2010 Free Software Foundation, Inc. +# Copyright (C) 2008, 2010, 2011 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -16,8 +16,6 @@ # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>. -EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o - # Only include multilibs for 680x0 and ColdFire CPUs with an MMU. M68K_MLIB_CPU += && ((CPU ~ "^m680") || (CPU ~ "^mcf")) && (FLAGS ~ "FL_MMU") diff --git a/gcc/config/m68k/t-m68kelf b/gcc/config/m68k/t-m68kelf deleted file mode 100644 index bea01dc4f49..00000000000 --- a/gcc/config/m68k/t-m68kelf +++ /dev/null @@ -1,4 +0,0 @@ -# from ../t-svr4 -EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o -# no pic for now -#CRTSTUFF_T_CFLAGS=-fpic diff --git a/gcc/config/m68k/t-mlibs b/gcc/config/m68k/t-mlibs index 11df31f210e..7be0c9f4fd4 100644 --- a/gcc/config/m68k/t-mlibs +++ b/gcc/config/m68k/t-mlibs @@ -92,6 +92,3 @@ endif # Remove the default CPU from the explicit exceptions. MULTILIB_EXCEPTIONS := \ $(patsubst mcpu=$(M68K_MLIB_DEFAULT)/%,%,$(MULTILIB_EXCEPTIONS)) - -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/config/m68k/t-slibgcc-elf-ver b/gcc/config/m68k/t-slibgcc-elf-ver deleted file mode 100644 index 6aac37cc08f..00000000000 --- a/gcc/config/m68k/t-slibgcc-elf-ver +++ /dev/null @@ -1,3 +0,0 @@ -# Bump the version number of the shared libgcc library - -SHLIB_SOVERSION = 2 diff --git a/gcc/config/m68k/t-uclinux b/gcc/config/m68k/t-uclinux index e1711a3443e..6994359dcce 100644 --- a/gcc/config/m68k/t-uclinux +++ b/gcc/config/m68k/t-uclinux @@ -1,4 +1,4 @@ -# Copyright (C) 2003, 2005, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2003, 2005, 2007, 2008, 2011 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -16,9 +16,6 @@ # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>. -# crti and crtn are provided by uClibc. -EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o - # Include multilibs for CPUs without an MMU or with FL_UCLINUX M68K_MLIB_CPU += && (!match(FLAGS, "FL_MMU") || match(FLAGS, "FL_UCLINUX")) |