1/*
2 * Copyright (c) 2013-2014, NVIDIA Corporation.  All rights reserved.
3 * Johnny Qiu <joqiu@nvidia.com>
4 * Shu Zhang <chazhang@nvidia.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *     * Redistributions of source code must retain the above copyright
10 *       notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 *       copyright notice, this list of conditions and the following
13 *       disclaimer in the documentation and/or other materials provided
14 *       with the distribution.
15 *     * Neither the name of The Linux Foundation nor the names of its
16 *       contributors may be used to endorse or promote products derived
17 *       from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <float.h>
33#include <private/bionic_asm.h>
34
35ENTRY(floor)    /* x in r0, r1 */
36
37        and             r3, r1, #0x80000000     /* sign(x) */
38        bic             r1, r1, #0x80000000     /* x = abs(x) */
39
40        /* extract exp of x */
41        lsr             r2, r1, #20
42        sub             r2, r2, #0x3fc
43        subs            r2, r2, #0x3            /* r2 <- exp */
44
45        /* |x| < 1.0? */
46        blt             .Lx_lt_one
47
48        /* x < 0? */
49        cmp             r3, #0
50        bne             .Lclr_frac_neg
51
52        /* |x| <= 2^20? */
53        cmp             r2, #20
54        ble             .Lclr_frac_r1
55
56        /* |x| < 2^52? */
57        cmp             r2, #52
58        blt             .Lclr_frac_r0
59
60        /* return x */
61        bx              lr
62
63.Lclr_frac_r1:
64        rsb             r2, r2, #20
65        lsr             r1, r1, r2
66        lsl             r1, r1, r2
67        mov             r0, #0
68        bx              lr
69
70.Lclr_frac_r0:
71        rsb             r2, r2, #52
72        lsr             r0, r0, r2
73        lsl             r0, r0, r2
74        bx              lr
75
76.Lclr_frac_neg:
77        /* |x| <= 2^20? */
78        cmp             r2, #20
79        ble             .Lclr_frac_r1_neg
80
81        /* |x| < 2^52? */
82        cmp             r2, #52
83        blt             .Lclr_frac_r0_neg
84
85        /* return x */
86        orr             r1, r1, #0x80000000
87        bx              lr
88
89.Lclr_frac_r1_neg:
90        rsb             r2, r2, #20
91        mov             r3, #1
92        lsl             r3, r3, r2
93        sub             r3, r3, #1
94        and             r3, r1, r3
95        orr             r3, r3, r0
96        lsr             r1, r1, r2
97        lsl             r1, r1, r2
98        mov             r0, #0
99        b               .Lreturn_x_neg
100
101.Lclr_frac_r0_neg:
102        rsb             r2, r2, #52
103        mov             r3, #1
104        lsl             r3, r3, r2
105        sub             r3, r3, #1
106        and             r3, r0, r3
107        lsr             r0, r0, r2
108        lsl             r0, r0, r2
109        b               .Lreturn_x_neg
110
111.Lx_lt_one:
112        /* x == +-0? */
113        cmp             r0, #0
114        cmpeq           r1, #0
115        orreq           r1, r1, r3
116        bxeq            lr
117
118        /* (x > 0) ? 0 : -1 */
119        mov             r1, #0x00100000
120        mov             r0, #0
121        cmp             r3, #0
122        movne           r1, #0xc0000000
123        sub             r1, r1, #0x00100000
124        bx              lr
125
126.Lreturn_x_neg:
127        cmp             r3, #0
128        orr             r1, r1, #0x80000000
129        bxeq            lr
130
131        vmov            d16, r0, r1
132        vmov.f64        d18, #1.0
133        vsub.f64        d16, d16, d18
134        vmov            r0, r1, d16
135        bx              lr
136
137END(floor)
138
139ALIAS_SYMBOL(floorl, floor);
140