Subversion Repositories HelenOS

Rev

Rev 2505 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2505 Rev 4687
1
/*
1
/*
2
 * Copyright (c) 2006 Josef Cejka
2
 * Copyright (c) 2006 Josef Cejka
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup genarch
29
/** @addtogroup genarch
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <genarch/softint/division.h>
35
#include <genarch/softint/division.h>
36
 
36
 
37
#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
37
#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
38
#define SGN(x) ((x) >= 0 ? 1 : 0)
38
#define SGN(x) ((x) >= 0 ? 1 : 0)
39
                     
39
                     
40
static unsigned int divandmod32(unsigned int a, unsigned int b,
40
static unsigned int divandmod32(unsigned int a, unsigned int b,
41
    unsigned int *remainder)
41
    unsigned int *remainder)
42
{
42
{
43
    unsigned int result;
43
    unsigned int result;
44
    int steps = sizeof(unsigned int) * 8;
44
    int steps = sizeof(unsigned int) * 8;
45
   
45
   
46
    *remainder = 0;
46
    *remainder = 0;
47
    result = 0;
47
    result = 0;
48
   
48
   
49
    if (b == 0) {
49
    if (b == 0) {
50
        /* FIXME: division by zero */
50
        /* FIXME: division by zero */
51
        return 0;
51
        return 0;
52
    }
52
    }
53
   
53
   
54
    if (a < b) {
54
    if (a < b) {
55
        *remainder = a;
55
        *remainder = a;
56
        return 0;
56
        return 0;
57
    }
57
    }
58
 
58
 
59
    for (; steps > 0; steps--) {
59
    for (; steps > 0; steps--) {
60
        /* shift one bit to remainder */
60
        /* shift one bit to remainder */
61
        *remainder = ((*remainder) << 1) | (( a >> 31) & 0x1);
61
        *remainder = ((*remainder) << 1) | (( a >> 31) & 0x1);
62
        result <<= 1;
62
        result <<= 1;
63
       
63
       
64
        if (*remainder >= b) {
64
        if (*remainder >= b) {
65
            *remainder -= b;
65
            *remainder -= b;
66
            result |= 0x1;
66
            result |= 0x1;
67
        }
67
        }
68
        a <<= 1;
68
        a <<= 1;
69
    }
69
    }
70
 
70
 
71
    return result;
71
    return result;
72
}
72
}
73
 
73
 
74
 
74
 
75
static unsigned long long divandmod64(unsigned long long a,
75
static unsigned long long divandmod64(unsigned long long a,
76
    unsigned long long b, unsigned long long *remainder)
76
    unsigned long long b, unsigned long long *remainder)
77
{
77
{
78
    unsigned long long result;
78
    unsigned long long result;
79
    int steps = sizeof(unsigned long long) * 8;
79
    int steps = sizeof(unsigned long long) * 8;
80
   
80
   
81
    *remainder = 0;
81
    *remainder = 0;
82
    result = 0;
82
    result = 0;
83
   
83
   
84
    if (b == 0) {
84
    if (b == 0) {
85
        /* FIXME: division by zero */
85
        /* FIXME: division by zero */
86
        return 0;
86
        return 0;
87
    }
87
    }
88
   
88
   
89
    if (a < b) {
89
    if (a < b) {
90
        *remainder = a;
90
        *remainder = a;
91
        return 0;
91
        return 0;
92
    }
92
    }
93
 
93
 
94
    for (; steps > 0; steps--) {
94
    for (; steps > 0; steps--) {
95
        /* shift one bit to remainder */
95
        /* shift one bit to remainder */
96
        *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
96
        *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
97
        result <<= 1;
97
        result <<= 1;
98
       
98
       
99
        if (*remainder >= b) {
99
        if (*remainder >= b) {
100
            *remainder -= b;
100
            *remainder -= b;
101
            result |= 0x1;
101
            result |= 0x1;
102
        }
102
        }
103
        a <<= 1;
103
        a <<= 1;
104
    }
104
    }
105
 
105
 
106
    return result;
106
    return result;
107
}
107
}
108
 
108
 
109
/* 32bit integer division */
109
/* 32bit integer division */
110
int __divsi3(int a, int b)
110
int __divsi3(int a, int b)
111
{
111
{
112
    unsigned int rem;
112
    unsigned int rem;
113
    int result;
113
    int result;
114
   
114
   
115
    result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
115
    result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
116
 
116
 
117
    if (SGN(a) == SGN(b))
117
    if (SGN(a) == SGN(b))
118
        return result;
118
        return result;
119
    return -result;
119
    return -result;
120
}
120
}
121
 
121
 
122
/* 64bit integer division */
122
/* 64bit integer division */
123
long long __divdi3(long long a, long long b)
123
long long __divdi3(long long a, long long b)
124
{
124
{
125
    unsigned long long rem;
125
    unsigned long long rem;
126
    long long result;
126
    long long result;
127
   
127
   
128
    result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
128
    result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
129
 
129
 
130
    if (SGN(a) == SGN(b))
130
    if (SGN(a) == SGN(b))
131
        return result;
131
        return result;
132
    return -result;
132
    return -result;
133
}
133
}
134
 
134
 
135
/* 32bit unsigned integer division */
135
/* 32bit unsigned integer division */
136
unsigned int __udivsi3(unsigned int a, unsigned int b)
136
unsigned int __udivsi3(unsigned int a, unsigned int b)
137
{
137
{
138
    unsigned int rem;
138
    unsigned int rem;
139
    return divandmod32(a, b, &rem);
139
    return divandmod32(a, b, &rem);
140
}
140
}
141
 
141
 
142
/* 64bit unsigned integer division */
142
/* 64bit unsigned integer division */
143
unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
143
unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
144
{
144
{
145
    unsigned long long  rem;
145
    unsigned long long  rem;
146
    return divandmod64(a, b, &rem);
146
    return divandmod64(a, b, &rem);
147
}
147
}
148
 
148
 
149
/* 32bit remainder of the signed division */
149
/* 32bit remainder of the signed division */
150
int __modsi3(int a, int b)
150
int __modsi3(int a, int b)
151
{
151
{
152
    unsigned int rem;
152
    unsigned int rem;
153
    divandmod32(a, b, &rem);
153
    divandmod32(a, b, &rem);
154
   
154
   
155
    /* if divident is negative, remainder must be too */
155
    /* if divident is negative, remainder must be too */
156
    if (!(SGN(a))) {
156
    if (!(SGN(a))) {
157
        return -((int) rem);
157
        return -((int) rem);
158
    }
158
    }
159
   
159
   
160
    return (int) rem;
160
    return (int) rem;
161
}
161
}
162
 
162
 
163
/* 64bit remainder of the signed division */
163
/* 64bit remainder of the signed division */
164
long long __moddi3(long long a,long  long b)
164
long long __moddi3(long long a,long  long b)
165
{
165
{
166
    unsigned long long rem;
166
    unsigned long long rem;
167
    divandmod64(a, b, &rem);
167
    divandmod64(a, b, &rem);
168
   
168
   
169
    /* if divident is negative, remainder must be too */
169
    /* if divident is negative, remainder must be too */
170
    if (!(SGN(a))) {
170
    if (!(SGN(a))) {
171
        return -((long long) rem);
171
        return -((long long) rem);
172
    }
172
    }
173
   
173
   
174
    return (long long) rem;
174
    return (long long) rem;
175
}
175
}
176
 
176
 
177
/* 32bit remainder of the unsigned division */
177
/* 32bit remainder of the unsigned division */
178
unsigned int __umodsi3(unsigned int a, unsigned int b)
178
unsigned int __umodsi3(unsigned int a, unsigned int b)
179
{
179
{
180
    unsigned int rem;
180
    unsigned int rem;
181
    divandmod32(a, b, &rem);
181
    divandmod32(a, b, &rem);
182
    return rem;
182
    return rem;
183
}
183
}
184
 
184
 
185
/* 64bit remainder of the unsigned division */
185
/* 64bit remainder of the unsigned division */
186
unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
186
unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
187
{
187
{
188
    unsigned long long rem;
188
    unsigned long long rem;
189
    divandmod64(a, b, &rem);
189
    divandmod64(a, b, &rem);
190
    return rem;
190
    return rem;
191
}
191
}
192
 
192
 
193
unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
193
unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
194
    unsigned long long *c)
194
    unsigned long long *c)
195
{
195
{
196
    return divandmod64(a, b, c);
196
    return divandmod64(a, b, c);
197
}
197
}
198
 
198
 
199
/** @}
199
/** @}
200
 */
200
 */
201
 
201