+/* Floating point library in optimized assembly for 8051
+ * Copyright (c) 2004, Paul Stoffregen, paul@pjrc.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This library 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#define SDCC_FLOAT_LIB
+#include <float.h>
+
+
+#ifdef FLOAT_ASM_MCS51
+
+// float __fsadd (float a, float b) __reentrant
+static void dummy(void) __naked
+{
+ __asm
+
+ // extract the two inputs, placing them into:
+ // sign exponent mantiassa
+ // ---- -------- ---------
+ // a: sign_a exp_a r4/r3/r2
+ // b: sign_b exp_b r7/r6/r5
+ //
+ // r1: used to extend precision of a's mantissa
+ // r0: general purpose loop counter
+
+ .globl ___fsadd
+___fsadd:
+ lcall fsgetargs
+
+ .globl fsadd_direct_entry
+fsadd_direct_entry:
+ // we're going to extend mantissa to 32 bits temporarily
+ mov r1, #0
+
+ // which exponent is greater?
+ mov a, exp_b
+ cjne a, exp_a, 00005$
+ sjmp 00011$
+00005$: jnc 00010$
+
+ // a's exponent was greater, so shift b's mantissa
+ lcall fs_swap_a_b
+
+00010$:
+ // b's exponent was greater, so shift a's mantissa
+ mov a, exp_b
+ clr c
+ subb a, exp_a
+ lcall fs_rshift_a // acc has # of shifts to do
+
+00011$:
+ // decide if we need to add or subtract
+ // sign_a and sign_b are stored in the flag bits of psw,
+ // so this little trick checks if the arguements ave the
+ // same sign.
+ mov a, psw
+ swap a
+ xrl a, psw
+ jb acc.1, 00022$
+
+00020$:
+ // add the mantissas (both positive or both negative)
+ mov a, r2
+ add a, r5
+ mov r2, a
+ mov a, r3
+ addc a, r6
+ mov r3, a
+ mov a, r4
+ addc a, r7
+ mov r4, a
+ // check for overflow past 24 bits
+ jnc 00021$
+ mov a, #1
+ lcall fs_rshift_a
+ mov a, r4
+ orl a, #0x80
+ mov r4, a
+00021$:
+ ljmp fs_round_and_return
+
+
+
+00022$:
+ // subtract the mantissas (one of them is negative)
+ clr c
+ mov a, r2
+ subb a, r5
+ mov r2, a
+ mov a, r3
+ subb a, r6
+ mov r3, a
+ mov a, r4
+ subb a, r7
+ mov r4, a
+ jnc 00025$
+ // if we get a negative result, turn it positive and
+ // flip the sign bit
+ clr c
+ clr a
+ subb a, r1
+ mov r1, a
+ clr a
+ subb a, r2
+ mov r2, a
+ clr a
+ subb a, r3
+ mov r3, a
+ clr a
+ subb a, r4
+ mov r4, a
+ cpl sign_a
+00025$:
+ lcall fs_normalize_a
+ ljmp fs_round_and_return
+
+ __endasm;
+}
+
+#else
+
+
/*
** libgcc support for software floating point.
** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
** uunet!motown!pipeline!phw
*/
-/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-
-#include <float.h>
-
union float_long
{
float f;
volatile long mant1, mant2;
volatile union float_long fl1, fl2;
volatile int exp1, exp2;
- volatile unsigned long sign = 0;
+ char sign = 0;
fl1.f = a1;
fl2.f = a2;
if (mant1 < 0)
{
mant1 = -mant1;
- sign = SIGNBIT;
+ sign = 1;
}
else if (!mant1)
return (0);
/* normalize */
- /* jwk: TODO: changing the next two whiles in nested ifs
- seriously breaks it. Why?????????????????? */
while (mant1<HIDDEN) {
mant1 <<= 1;
exp1--;
}
+ /* round off */
while (mant1 & 0xff000000) {
- // round off
if (mant1&1)
mant1 += 2;
- mant1 >>= 1 ;
+ mant1 >>= 1;
exp1++;
}
mant1 &= ~HIDDEN;
/* pack up and go home */
- fl1.l = PACK (sign, (unsigned long) exp1, mant1);
-
+ if (exp1 >= 0x100)
+ fl1.l = (sign ? SIGNBIT : 0) | __INFINITY;
+ else if (exp1 < 0)
+ fl1.l = 0;
+ else
+ fl1.l = PACK (sign ? SIGNBIT : 0 , exp1, mant1);
return (fl1.f);
}
+
+#endif