1/* Copyright (c) 2002 Michael Stumpf <mistumpf@de.pepperl-fuchs.com> 2 Copyright (c) 2006,2009 Dmitry Xmelkov 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are met: 7 8 * Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in 12 the documentation and/or other materials provided with the 13 distribution. 14 * Neither the name of the copyright holders nor the names of 15 contributors may be used to endorse or promote products derived 16 from this software without specific prior written permission. 17 18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 POSSIBILITY OF SUCH DAMAGE. */ 29 30/* $Id: modf.S 2473 2015-04-09 08:10:22Z pitchumani $ */ 31 32#if !defined(__AVR_TINY__) 33 34#include "fp32def.h" 35#include "asmdef.h" 36 37/* double modf (double x, double *iptr); 38 39 The modf() function breaks the argument x into an integral part and a 40 fractional part, each of which has the same sign as x. The integral part 41 is stored in iptr. 42 This implementation skips writing by zero pointer. 43 */ 44 45#define iptr_lo r20 46 47ENTRY modf 48ENTRY modff 49 ; save iptr 50 X_movw ZL, iptr_lo 51 ; XH = exponent field 52 X_movw XL, rA2 53 lsl XL 54 rol XH 55 ; B = A 56 X_movw rB0, rA0 57 X_movw rB2, rA2 58 ; Is there an integral part? 59 subi XH, 127 ; exp of 1.0 60 brsh 1f 61 ; fabs(x) < 1.0: *iptr = copysign(0, x), return x 62 clr rB0 63 clr rB1 64 clr rB2 65 andi rB3, 0x80 66 rjmp .L_write 67 ; Is there a fraction part? 681: subi XH, 23 69 brsh 4f ; no fraction part 70 ; check fraction: B >>= 23 - (exp-127) 71 mov XL, XH ; Now XH is -23..-1 72 clr r0 ; to control, is the fraction zero? 732: lsr rB2 74 ror rB1 75 ror rB0 76 adc r0, r1 77 inc XL 78 brmi 2b 79 tst r0 80 breq .L_nfrc ; fraction == 0 81 ; restore and clear fraction: B <<= 23 - (exp-127) 823: lsl rB0 83 rol rB1 84 rol rB2 85 inc XH 86 brmi 3b 87 ; write B 88 rcall .L_write 89 ; return nonzero fraction: A - B 90 XJMP _U(__subsf3) 91 ; exponent too big: compare with smallest NaN (0x7f800001) 924: cpi rA0, 1 93 cpc rA1, r1 94 ldi XL, 0x80 95 cpc rA2, XL 96 sbci XH, 128 - 23 97 brsh .L_write ; NaN: write and return as is 98 ; fraction == 0 99.L_nfrc: 100 X_movw rB0, rA0 101 X_movw rB2, rA2 102 ; A = 0.0 with sign 103 clr rA0 104 clr rA1 105 clr rA2 106 andi rA3, 0x80 107.L_write: 108 adiw ZL, 0 ; skip writing with NULL pointer 109 breq 1f 110 st Z, rB0 111 std Z+1, rB1 112 std Z+2, rB2 113 std Z+3, rB3 1141: ret 115ENDFUNC 116 117#endif /* !defined(__AVR_TINY__) */ 118