1/* Copyright (c) 2007 Dmitry Xmelkov 2 All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above copyright 10 notice, this list of conditions and the following disclaimer in 11 the documentation and/or other materials provided with the 12 distribution. 13 * Neither the name of the copyright holders nor the names of 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 POSSIBILITY OF SUCH DAMAGE. */ 28 29/* $Id: lround.S 2473 2015-04-09 08:10:22Z pitchumani $ */ 30 31 32#if !defined(__AVR_TINY__) 33 34#include "fp32def.h" 35#include "asmdef.h" 36 37/* long lround (double A); 38 The lround() function rounds A to the nearest integer, but rounds 39 halfway cases away from zero (instead of to the nearest even integer). 40 This function is similar to round() function, but it differs in 41 type of return value and in that an overflow is possible. 42 Return: 43 The rounded long integer value. If A is infinite, NaN or an overflow 44 was, this realization returns the LONG_MIN value (0x80000000). 45 46 Algorithm roughly: 47 - split 48 - shift mantissa according to exponent 49 - add 0.5 to round 50 - restore the sign 51 52 Objections to saturation are listen in __fixunssfsi.S file. 53 */ 54 55ENTRY lround 56 XCALL _U(__fp_splitA) 57 brcs .L_err 58 ; A is finite 59 subi rA3, 126 ; exponent field of 0.5 60 brlo .L_zr ; A is too small 61 ; fabs(A) >= 0x0.800000p+00 62 subi rA3, 24 63 brlo 2f ; shtft to right and round 64 breq .L_sign ; no shift 65 ; fabs(A) >= 0x0.800000p+25 66 cpi rA3, 8 67 brsh .L_err ; A is too big 68 69 ; 0x0.800000p+25 <= fabs(A) <= 0x0.ffffffp+31 --> shift to left by 1..7 70 mov r0, rA3 ; shift counter 71 clr rA3 ; MSB 72 ; rA3.2.1.0 <<= r0 731: lsl rA0 74 rol rA1 75 rol rA2 76 rol rA3 77 dec r0 78 brne 1b 79 rjmp .L_sign 80 81 ; quick shift to right by 8 825: mov r0, rA0 ; save for possible round 83 mov rA0, rA1 84 mov rA1, rA2 85 clr rA2 86 subi rA3, -8 87 brne 2f 88 lsl r0 ; restore C 89 rjmp 4f ; and round 90 ; 0x0.800000p+00 <= fabs(A) <= 0x0.ffffffp+23 91 ; Shift A to right by 1 (rA3 == -1) .. 24 (rA3 == -24) positions and 92 ; round. 932: cpi rA3, -7 94 brlt 5b 95 ; shift to right by 1..7 (slow) 963: lsr rA2 97 ror rA1 98 ror rA0 ; --> C 99 inc rA3 ; C is not changed 100 brne 3b 101 ; Round. Now flag C is set if fractional is >= 0.5 1024: adc rA0, r1 103 adc rA1, r1 104 adc rA2, r1 ; rA2 was <= 0x7f, so rA3 will not changed 105 106 ; restore the sign and return 107.L_sign: 108 brtc 6f 109 com rA3 110 com rA2 111 com rA1 112 neg rA0 113 sbci rA1, -1 114 sbci rA2, -1 115 sbci rA3, -1 1166: ret 117 118.L_err: set ; force return 0x80000000 119 XJMP _U(__fp_szero) 120 121.L_zr: XJMP _U(__fp_zero) ; return 0x00000000 122 123ENDFUNC 124 125#endif /* !defined(__AVR_TINY__) */ 126