X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device%2Flib%2F_fsdiv.c;h=1768ec46a9b21c9ee3d2e5c0b29d6f833e2f3e2a;hb=62b66640e43568550cf42435f62f91cead38927b;hp=a89d698b5f0d4efe93297d9ea775c69ee1a1c34d;hpb=5a964d04cfff5accede4e488135633bd1a780576;p=fw%2Fsdcc diff --git a/device/lib/_fsdiv.c b/device/lib/_fsdiv.c index a89d698b..1768ec46 100644 --- a/device/lib/_fsdiv.c +++ b/device/lib/_fsdiv.c @@ -1,3 +1,211 @@ +/* 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 + + +#ifdef FLOAT_ASM_MCS51 + +// float __fsdiv (float a, float b) reentrant +static void dummy(void) _naked +{ + _asm + .globl ___fsdiv +___fsdiv: + // 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 + + lcall fsgetargs + + // compute final sign bit + jnb sign_b, 00001$ + cpl sign_a +00001$: + + // if divisor is zero, return infinity + cjne r7, #0, 00002$ + ljmp fs_return_inf +00002$: + // if dividend is zero, return zero + cjne r4, #0, 00003$ + ljmp fs_return_zero +00003$: + + // subtract exponents + clr c + mov a, exp_a + subb a, exp_b + add a, #127 + mov exp_a, a + + // need extra bits on a's mantissa +#ifdef FLOAT_FULL_ACCURACY + clr c + mov a, r5 + subb a, r2 + mov a, r6 + subb a, r3 + mov a, r7 + subb a, r4 + jc 00005$ + dec exp_a + clr c + mov a, r2 + rlc a + mov r1, a + mov a, r3 + rlc a + mov r2, a + mov a, r4 + rlc a + mov r3, a + clr a + rlc a + mov r4, a + sjmp 00006$ +00005$: +#endif + clr a + xch a, r4 + xch a, r3 + xch a, r2 + mov r1, a +00006$: + + // begin long division + push exp_a +#ifdef FLOAT_FULL_ACCURACY + mov b, #25 +#else + mov b, #24 +#endif +00010$: + // compare + clr c + mov a, r1 + subb a, r5 + mov a, r2 + subb a, r6 + mov a, r3 + subb a, r7 + mov a, r4 + subb a, #0 // carry==0 if mant1 >= mant2 + +#ifdef FLOAT_FULL_ACCURACY + djnz b, 00011$ + sjmp 00015$ +00011$: +#endif + jc 00012$ + // subtract + mov a, r1 + subb a, r5 + mov r1, a + mov a, r2 + subb a, r6 + mov r2, a + mov a, r3 + subb a, r7 + mov r3, a + mov a, r4 + subb a, #0 + mov r4, a + clr c + +00012$: + // shift result + cpl c + mov a, r0 + rlc a + mov r0, a + mov a, dpl + rlc a + mov dpl, a + mov a, dph + rlc a + mov dph, a + + // shift partial remainder + clr c + mov a, r1 + rlc a + mov r1, a + mov a, r2 + rlc a + mov r2, a + mov a, r3 + rlc a + mov r3, a + mov a, r4 + rlc a + mov r4, a + +#ifdef FLOAT_FULL_ACCURACY + sjmp 00010$ +00015$: +#else + djnz b, 00010$ +#endif + + // now we've got a division result, so all we need to do + // is round off properly, normalize and output a float + +#ifdef FLOAT_FULL_ACCURACY + cpl c + clr a + mov r1, a + addc a, r0 + mov r2, a + clr a + addc a, dpl + mov r3, a + clr a + addc a, dph + mov r4, a + pop exp_a + jnc 00016$ + inc exp_a + mov r4, #0x80 +00016$: +#else + mov r1, #0 + mov a, r0 + mov r2, a + mov r3, dpl + mov r4, dph + pop exp_a +#endif + + lcall fs_normalize_a + ljmp fs_zerocheck_return + _endasm; +} + +#else + + + + /* ** libgcc support for software floating point. ** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. @@ -16,7 +224,6 @@ /* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */ -#include union float_long { @@ -93,3 +300,5 @@ float __fsdiv (float a1, float a2) return (fl1.f); } +#endif +