OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [acpi/] [utilities/] [utmath.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*******************************************************************************
2
 *
3
 * Module Name: utmath - Integer math support routines
4
 *
5
 ******************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2004, R. Byron Moore
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
 
45
#include <acpi/acpi.h>
46
 
47
 
48
#define _COMPONENT          ACPI_UTILITIES
49
         ACPI_MODULE_NAME    ("utmath")
50
 
51
/*
52
 * Support for double-precision integer divide.  This code is included here
53
 * in order to support kernel environments where the double-precision math
54
 * library is not available.
55
 */
56
 
57
#ifndef ACPI_USE_NATIVE_DIVIDE
58
/*******************************************************************************
59
 *
60
 * FUNCTION:    acpi_ut_short_divide
61
 *
62
 * PARAMETERS:  in_dividend         - Pointer to the dividend
63
 *              Divisor             - 32-bit divisor
64
 *              out_quotient        - Pointer to where the quotient is returned
65
 *              out_remainder       - Pointer to where the remainder is returned
66
 *
67
 * RETURN:      Status (Checks for divide-by-zero)
68
 *
69
 * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
70
 *              divide and modulo.  The result is a 64-bit quotient and a
71
 *              32-bit remainder.
72
 *
73
 ******************************************************************************/
74
 
75
acpi_status
76
acpi_ut_short_divide (
77
        acpi_integer                    *in_dividend,
78
        u32                             divisor,
79
        acpi_integer                    *out_quotient,
80
        u32                             *out_remainder)
81
{
82
        union uint64_overlay            dividend;
83
        union uint64_overlay            quotient;
84
        u32                             remainder32;
85
 
86
 
87
        ACPI_FUNCTION_TRACE ("ut_short_divide");
88
 
89
        dividend.full = *in_dividend;
90
 
91
        /* Always check for a zero divisor */
92
 
93
        if (divisor == 0) {
94
                ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
95
                return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
96
        }
97
 
98
        /*
99
         * The quotient is 64 bits, the remainder is always 32 bits,
100
         * and is generated by the second divide.
101
         */
102
        ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor,
103
                          quotient.part.hi, remainder32);
104
        ACPI_DIV_64_BY_32 (remainder32, dividend.part.lo,  divisor,
105
                          quotient.part.lo, remainder32);
106
 
107
        /* Return only what was requested */
108
 
109
        if (out_quotient) {
110
                *out_quotient = quotient.full;
111
        }
112
        if (out_remainder) {
113
                *out_remainder = remainder32;
114
        }
115
 
116
        return_ACPI_STATUS (AE_OK);
117
}
118
 
119
 
120
/*******************************************************************************
121
 *
122
 * FUNCTION:    acpi_ut_divide
123
 *
124
 * PARAMETERS:  in_dividend         - Pointer to the dividend
125
 *              in_divisor          - Pointer to the divisor
126
 *              out_quotient        - Pointer to where the quotient is returned
127
 *              out_remainder       - Pointer to where the remainder is returned
128
 *
129
 * RETURN:      Status (Checks for divide-by-zero)
130
 *
131
 * DESCRIPTION: Perform a divide and modulo.
132
 *
133
 ******************************************************************************/
134
 
135
acpi_status
136
acpi_ut_divide (
137
        acpi_integer                    *in_dividend,
138
        acpi_integer                    *in_divisor,
139
        acpi_integer                    *out_quotient,
140
        acpi_integer                    *out_remainder)
141
{
142
        union uint64_overlay            dividend;
143
        union uint64_overlay            divisor;
144
        union uint64_overlay            quotient;
145
        union uint64_overlay            remainder;
146
        union uint64_overlay            normalized_dividend;
147
        union uint64_overlay            normalized_divisor;
148
        u32                             partial1;
149
        union uint64_overlay            partial2;
150
        union uint64_overlay            partial3;
151
 
152
 
153
        ACPI_FUNCTION_TRACE ("ut_divide");
154
 
155
 
156
        /* Always check for a zero divisor */
157
 
158
        if (*in_divisor == 0) {
159
                ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
160
                return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
161
        }
162
 
163
        divisor.full  = *in_divisor;
164
        dividend.full = *in_dividend;
165
        if (divisor.part.hi == 0) {
166
                /*
167
                 * 1) Simplest case is where the divisor is 32 bits, we can
168
                 * just do two divides
169
                 */
170
                remainder.part.hi = 0;
171
 
172
                /*
173
                 * The quotient is 64 bits, the remainder is always 32 bits,
174
                 * and is generated by the second divide.
175
                 */
176
                ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor.part.lo,
177
                                  quotient.part.hi, partial1);
178
                ACPI_DIV_64_BY_32 (partial1, dividend.part.lo, divisor.part.lo,
179
                                  quotient.part.lo, remainder.part.lo);
180
        }
181
 
182
        else {
183
                /*
184
                 * 2) The general case where the divisor is a full 64 bits
185
                 * is more difficult
186
                 */
187
                quotient.part.hi   = 0;
188
                normalized_dividend = dividend;
189
                normalized_divisor = divisor;
190
 
191
                /* Normalize the operands (shift until the divisor is < 32 bits) */
192
 
193
                do {
194
                        ACPI_SHIFT_RIGHT_64 (normalized_divisor.part.hi,
195
                                         normalized_divisor.part.lo);
196
                        ACPI_SHIFT_RIGHT_64 (normalized_dividend.part.hi,
197
                                         normalized_dividend.part.lo);
198
 
199
                } while (normalized_divisor.part.hi != 0);
200
 
201
                /* Partial divide */
202
 
203
                ACPI_DIV_64_BY_32 (normalized_dividend.part.hi,
204
                                  normalized_dividend.part.lo,
205
                                  normalized_divisor.part.lo,
206
                                  quotient.part.lo, partial1);
207
 
208
                /*
209
                 * The quotient is always 32 bits, and simply requires adjustment.
210
                 * The 64-bit remainder must be generated.
211
                 */
212
                partial1      = quotient.part.lo * divisor.part.hi;
213
                partial2.full = (acpi_integer) quotient.part.lo * divisor.part.lo;
214
                partial3.full = (acpi_integer) partial2.part.hi + partial1;
215
 
216
                remainder.part.hi = partial3.part.lo;
217
                remainder.part.lo = partial2.part.lo;
218
 
219
                if (partial3.part.hi == 0) {
220
                        if (partial3.part.lo >= dividend.part.hi) {
221
                                if (partial3.part.lo == dividend.part.hi) {
222
                                        if (partial2.part.lo > dividend.part.lo) {
223
                                                quotient.part.lo--;
224
                                                remainder.full -= divisor.full;
225
                                        }
226
                                }
227
                                else {
228
                                        quotient.part.lo--;
229
                                        remainder.full -= divisor.full;
230
                                }
231
                        }
232
 
233
                        remainder.full    = remainder.full - dividend.full;
234
                        remainder.part.hi = (u32) -((s32) remainder.part.hi);
235
                        remainder.part.lo = (u32) -((s32) remainder.part.lo);
236
 
237
                        if (remainder.part.lo) {
238
                                remainder.part.hi--;
239
                        }
240
                }
241
        }
242
 
243
        /* Return only what was requested */
244
 
245
        if (out_quotient) {
246
                *out_quotient = quotient.full;
247
        }
248
        if (out_remainder) {
249
                *out_remainder = remainder.full;
250
        }
251
 
252
        return_ACPI_STATUS (AE_OK);
253
}
254
 
255
#else
256
 
257
/*******************************************************************************
258
 *
259
 * FUNCTION:    acpi_ut_short_divide, acpi_ut_divide
260
 *
261
 * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
262
 *              1) The target is a 64-bit platform and therefore 64-bit
263
 *                 integer math is supported directly by the machine.
264
 *              2) The target is a 32-bit or 16-bit platform, and the
265
 *                 double-precision integer math library is available to
266
 *                 perform the divide.
267
 *
268
 ******************************************************************************/
269
 
270
acpi_status
271
acpi_ut_short_divide (
272
        acpi_integer                    *in_dividend,
273
        u32                             divisor,
274
        acpi_integer                    *out_quotient,
275
        u32                             *out_remainder)
276
{
277
 
278
        ACPI_FUNCTION_TRACE ("ut_short_divide");
279
 
280
 
281
        /* Always check for a zero divisor */
282
 
283
        if (divisor == 0) {
284
                ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
285
                return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
286
        }
287
 
288
        /* Return only what was requested */
289
 
290
        if (out_quotient) {
291
                *out_quotient = *in_dividend / divisor;
292
        }
293
        if (out_remainder) {
294
                *out_remainder = (u32) *in_dividend % divisor;
295
        }
296
 
297
        return_ACPI_STATUS (AE_OK);
298
}
299
 
300
acpi_status
301
acpi_ut_divide (
302
        acpi_integer                    *in_dividend,
303
        acpi_integer                    *in_divisor,
304
        acpi_integer                    *out_quotient,
305
        acpi_integer                    *out_remainder)
306
{
307
        ACPI_FUNCTION_TRACE ("ut_divide");
308
 
309
 
310
        /* Always check for a zero divisor */
311
 
312
        if (*in_divisor == 0) {
313
                ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
314
                return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
315
        }
316
 
317
 
318
        /* Return only what was requested */
319
 
320
        if (out_quotient) {
321
                *out_quotient = *in_dividend / *in_divisor;
322
        }
323
        if (out_remainder) {
324
                *out_remainder = *in_dividend % *in_divisor;
325
        }
326
 
327
        return_ACPI_STATUS (AE_OK);
328
}
329
 
330
#endif
331
 
332
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.