~ubuntu-branches/ubuntu/raring/avr-libc/raring-proposed

« back to all changes in this revision

Viewing changes to libm/fplib/lrint.S

  • Committer: Bazaar Package Importer
  • Author(s): Hakan Ardo
  • Date: 2008-04-04 17:05:32 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404170532-tiwwl2e2qln7ri0w
Tags: 1:1.6.2-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: lrint.S,v 1.1 2007/12/01 04:39:05 dmix Exp $ */
 
30
 
 
31
#include "fp32def.h"
 
32
#include "asmdef.h"
 
33
 
 
34
/* long lrint (double A);
 
35
     The lrint() function rounds A to the nearest integer, rounding the
 
36
     halfway cases to the even integer direction. (That is both 1.5 and
 
37
     2.5 values are rounded to 2). This function is similar to rint()
 
38
     function, but it differs in type of return value and in that an
 
39
     overflow is possible.
 
40
   Return:
 
41
     The rounded long integer value. If A is not a finite number or an
 
42
     overflow was, this realization returns the LONG_MIN value (0x80000000).
 
43
 
 
44
   Algorithm roughly:
 
45
     - split
 
46
     - shift mantissa according to exponent
 
47
     - round (if shift was to right)
 
48
     - restore the sign
 
49
 */
 
50
 
 
51
ENTRY lrint
 
52
        rcall   _U(__fp_splitA)
 
53
        brcs    .L_err
 
54
  ; A is finite
 
55
        subi    rA3, 126        ; exponent field of 0.5
 
56
        brlo    .L_zr           ; A is too small
 
57
  ; fabs(A) >= 0x0.800000p+00
 
58
        subi    rA3, 24
 
59
        brlo    .L_right        ; shtft to right and round
 
60
        breq    .L_sign         ; no shift
 
61
  ; fabs(A) >= 0x0.800000p+25
 
62
        cpi     rA3, 8
 
63
        brsh    .L_err          ; fabs(A) is too big
 
64
 
 
65
  ; 0x0.800000p+25 <= fabs(A) <= 0x0.ffffffp+31  --> shift to left by 1..7
 
66
        mov     r0, rA3         ; shift counter
 
67
        clr     rA3             ; MSB
 
68
  ; rA3.2.1.0 <<= r0
 
69
1:      lsl     rA0
 
70
        rol     rA1
 
71
        rol     rA2
 
72
        rol     rA3
 
73
        dec     r0
 
74
        brne    1b
 
75
        rjmp    .L_sign
 
76
 
 
77
  ; 0x0.800000p+00 <= fabs(A) <= 0x0.ffffffp+23
 
78
  ; Shift A to right by 1 (rA3 == -1) .. 24 (rA3 == -24) positions and
 
79
  ; round.
 
80
.L_right:
 
81
        clr     rAE             ; accumulator for lower bits
 
82
2:      cpi     rA3, -7
 
83
        brge    3f
 
84
  ; Quick shift to right by 8. The trick with rAE is needed to save info
 
85
  ; about the lowerest bits. This will be used to compare fraction with
 
86
  ; 0.5 value.
 
87
        cpse    rAE, r1
 
88
        ldi     rAE, 1
 
89
        or      rAE, rA0
 
90
        mov     rA0, rA1
 
91
        mov     rA1, rA2
 
92
        clr     rA2
 
93
        subi    rA3, -8
 
94
        brne    2b
 
95
        rjmp    .L_round
 
96
  ; shift to right by 1..7 (slow)
 
97
3:      lsr     rA2
 
98
        ror     rA1
 
99
        ror     rA0
 
100
        ror     rAE
 
101
        brcc    4f
 
102
        ori     rAE, 1          ; save flag that lowerst bits are not all 0
 
103
4:      inc     rA3
 
104
        brne    3b
 
105
  ; round
 
106
.L_round:
 
107
        lsl     rAE
 
108
        brcc    .L_sign         ; fraction < 0.5
 
109
        brne    7f              ; fraction > 0.5
 
110
        sbrs    rA0, 0
 
111
        rjmp    .L_sign         ; fraction == 0.5 and value is even
 
112
7:      subi    rA0, -1
 
113
        sbci    rA1, -1
 
114
        sbci    rA2, -1         ; rA2 was <= 0x7f, so rA3 will not changed
 
115
 
 
116
  ; restore the sign and return
 
117
.L_sign:
 
118
        brtc    6f
 
119
        com     rA3
 
120
        com     rA2
 
121
        com     rA1
 
122
        neg     rA0
 
123
        sbci    rA1, -1
 
124
        sbci    rA2, -1
 
125
        sbci    rA3, -1
 
126
6:      ret
 
127
 
 
128
.L_err: set                     ; force return 0x80000000
 
129
        rjmp    _U(__fp_szero)
 
130
 
 
131
.L_zr:  rjmp    _U(__fp_zero)   ; return 0x00000000
 
132
 
 
133
ENDFUNC