Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/*******************************************************************************
2
 *
3
 * Module Name: utmath - Integer math support routines
4
 *
5
 ******************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
 
117
#define __UTMATH_C__
118
 
119
#include "acpi.h"
120
#include "accommon.h"
121
 
122
 
123
#define _COMPONENT          ACPI_UTILITIES
124
        ACPI_MODULE_NAME    ("utmath")
125
 
126
/*
2216 Serge 127
 * Optional support for 64-bit double-precision integer divide. This code
128
 * is configurable and is implemented in order to support 32-bit kernel
129
 * environments where a 64-bit double-precision math library is not available.
130
 *
131
 * Support for a more normal 64-bit divide/modulo (with check for a divide-
132
 * by-zero) appears after this optional section of code.
1498 serge 133
 */
2216 Serge 134
#ifndef ACPI_USE_NATIVE_DIVIDE
1498 serge 135
 
2216 Serge 136
/* Structures used only for 64-bit divide */
137
 
138
typedef struct uint64_struct
139
{
140
    UINT32                          Lo;
141
    UINT32                          Hi;
142
 
143
} UINT64_STRUCT;
144
 
145
typedef union uint64_overlay
146
{
147
    UINT64                          Full;
148
    UINT64_STRUCT                   Part;
149
 
150
} UINT64_OVERLAY;
151
 
152
 
1498 serge 153
/*******************************************************************************
154
 *
155
 * FUNCTION:    AcpiUtShortDivide
156
 *
157
 * PARAMETERS:  Dividend            - 64-bit dividend
158
 *              Divisor             - 32-bit divisor
159
 *              OutQuotient         - Pointer to where the quotient is returned
160
 *              OutRemainder        - Pointer to where the remainder is returned
161
 *
162
 * RETURN:      Status (Checks for divide-by-zero)
163
 *
164
 * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
165
 *              divide and modulo.  The result is a 64-bit quotient and a
166
 *              32-bit remainder.
167
 *
168
 ******************************************************************************/
169
 
170
ACPI_STATUS
171
AcpiUtShortDivide (
172
    UINT64                  Dividend,
173
    UINT32                  Divisor,
174
    UINT64                  *OutQuotient,
175
    UINT32                  *OutRemainder)
176
{
177
    UINT64_OVERLAY          DividendOvl;
178
    UINT64_OVERLAY          Quotient;
179
    UINT32                  Remainder32;
180
 
181
 
182
    ACPI_FUNCTION_TRACE (UtShortDivide);
183
 
184
 
185
    /* Always check for a zero divisor */
186
 
187
    if (Divisor == 0)
188
    {
189
        ACPI_ERROR ((AE_INFO, "Divide by zero"));
190
        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
191
    }
192
 
193
    DividendOvl.Full = Dividend;
194
 
195
    /*
196
     * The quotient is 64 bits, the remainder is always 32 bits,
197
     * and is generated by the second divide.
198
     */
199
    ACPI_DIV_64_BY_32 (0, DividendOvl.Part.Hi, Divisor,
200
                       Quotient.Part.Hi, Remainder32);
201
    ACPI_DIV_64_BY_32 (Remainder32, DividendOvl.Part.Lo, Divisor,
202
                       Quotient.Part.Lo, Remainder32);
203
 
204
    /* Return only what was requested */
205
 
206
    if (OutQuotient)
207
    {
208
        *OutQuotient = Quotient.Full;
209
    }
210
    if (OutRemainder)
211
    {
212
        *OutRemainder = Remainder32;
213
    }
214
 
215
    return_ACPI_STATUS (AE_OK);
216
}
217
 
218
 
219
/*******************************************************************************
220
 *
221
 * FUNCTION:    AcpiUtDivide
222
 *
223
 * PARAMETERS:  InDividend          - Dividend
224
 *              InDivisor           - Divisor
225
 *              OutQuotient         - Pointer to where the quotient is returned
226
 *              OutRemainder        - Pointer to where the remainder is returned
227
 *
228
 * RETURN:      Status (Checks for divide-by-zero)
229
 *
230
 * DESCRIPTION: Perform a divide and modulo.
231
 *
232
 ******************************************************************************/
233
 
234
ACPI_STATUS
235
AcpiUtDivide (
236
    UINT64                  InDividend,
237
    UINT64                  InDivisor,
238
    UINT64                  *OutQuotient,
239
    UINT64                  *OutRemainder)
240
{
241
    UINT64_OVERLAY          Dividend;
242
    UINT64_OVERLAY          Divisor;
243
    UINT64_OVERLAY          Quotient;
244
    UINT64_OVERLAY          Remainder;
245
    UINT64_OVERLAY          NormalizedDividend;
246
    UINT64_OVERLAY          NormalizedDivisor;
247
    UINT32                  Partial1;
248
    UINT64_OVERLAY          Partial2;
249
    UINT64_OVERLAY          Partial3;
250
 
251
 
252
    ACPI_FUNCTION_TRACE (UtDivide);
253
 
254
 
255
    /* Always check for a zero divisor */
256
 
257
    if (InDivisor == 0)
258
    {
259
        ACPI_ERROR ((AE_INFO, "Divide by zero"));
260
        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
261
    }
262
 
263
    Divisor.Full  = InDivisor;
264
    Dividend.Full = InDividend;
265
    if (Divisor.Part.Hi == 0)
266
    {
267
        /*
268
         * 1) Simplest case is where the divisor is 32 bits, we can
269
         * just do two divides
270
         */
271
        Remainder.Part.Hi = 0;
272
 
273
        /*
274
         * The quotient is 64 bits, the remainder is always 32 bits,
275
         * and is generated by the second divide.
276
         */
277
        ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo,
278
                           Quotient.Part.Hi, Partial1);
279
        ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo,
280
                           Quotient.Part.Lo, Remainder.Part.Lo);
281
    }
282
 
283
    else
284
    {
285
        /*
286
         * 2) The general case where the divisor is a full 64 bits
287
         * is more difficult
288
         */
289
        Quotient.Part.Hi   = 0;
290
        NormalizedDividend = Dividend;
291
        NormalizedDivisor  = Divisor;
292
 
293
        /* Normalize the operands (shift until the divisor is < 32 bits) */
294
 
295
        do
296
        {
297
            ACPI_SHIFT_RIGHT_64 (NormalizedDivisor.Part.Hi,
298
                                 NormalizedDivisor.Part.Lo);
299
            ACPI_SHIFT_RIGHT_64 (NormalizedDividend.Part.Hi,
300
                                 NormalizedDividend.Part.Lo);
301
 
302
        } while (NormalizedDivisor.Part.Hi != 0);
303
 
304
        /* Partial divide */
305
 
306
        ACPI_DIV_64_BY_32 (NormalizedDividend.Part.Hi,
307
                           NormalizedDividend.Part.Lo,
308
                           NormalizedDivisor.Part.Lo,
309
                           Quotient.Part.Lo, Partial1);
310
 
311
        /*
312
         * The quotient is always 32 bits, and simply requires adjustment.
313
         * The 64-bit remainder must be generated.
314
         */
315
        Partial1      = Quotient.Part.Lo * Divisor.Part.Hi;
316
        Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo;
317
        Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1;
318
 
319
        Remainder.Part.Hi = Partial3.Part.Lo;
320
        Remainder.Part.Lo = Partial2.Part.Lo;
321
 
322
        if (Partial3.Part.Hi == 0)
323
        {
324
            if (Partial3.Part.Lo >= Dividend.Part.Hi)
325
            {
326
                if (Partial3.Part.Lo == Dividend.Part.Hi)
327
                {
328
                    if (Partial2.Part.Lo > Dividend.Part.Lo)
329
                    {
330
                        Quotient.Part.Lo--;
331
                        Remainder.Full -= Divisor.Full;
332
                    }
333
                }
334
                else
335
                {
336
                    Quotient.Part.Lo--;
337
                    Remainder.Full -= Divisor.Full;
338
                }
339
            }
340
 
341
            Remainder.Full    = Remainder.Full - Dividend.Full;
342
            Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi);
343
            Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo);
344
 
345
            if (Remainder.Part.Lo)
346
            {
347
                Remainder.Part.Hi--;
348
            }
349
        }
350
    }
351
 
352
    /* Return only what was requested */
353
 
354
    if (OutQuotient)
355
    {
356
        *OutQuotient = Quotient.Full;
357
    }
358
    if (OutRemainder)
359
    {
360
        *OutRemainder = Remainder.Full;
361
    }
362
 
363
    return_ACPI_STATUS (AE_OK);
364
}
365
 
366
#else
367
 
368
/*******************************************************************************
369
 *
370
 * FUNCTION:    AcpiUtShortDivide, AcpiUtDivide
371
 *
372
 * PARAMETERS:  See function headers above
373
 *
374
 * DESCRIPTION: Native versions of the UtDivide functions. Use these if either
375
 *              1) The target is a 64-bit platform and therefore 64-bit
376
 *                 integer math is supported directly by the machine.
377
 *              2) The target is a 32-bit or 16-bit platform, and the
378
 *                 double-precision integer math library is available to
379
 *                 perform the divide.
380
 *
381
 ******************************************************************************/
382
 
383
ACPI_STATUS
384
AcpiUtShortDivide (
385
    UINT64                  InDividend,
386
    UINT32                  Divisor,
387
    UINT64                  *OutQuotient,
388
    UINT32                  *OutRemainder)
389
{
390
 
391
    ACPI_FUNCTION_TRACE (UtShortDivide);
392
 
393
 
394
    /* Always check for a zero divisor */
395
 
396
    if (Divisor == 0)
397
    {
398
        ACPI_ERROR ((AE_INFO, "Divide by zero"));
399
        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
400
    }
401
 
402
    /* Return only what was requested */
403
 
404
    if (OutQuotient)
405
    {
406
        *OutQuotient = InDividend / Divisor;
407
    }
408
    if (OutRemainder)
409
    {
410
        *OutRemainder = (UINT32) (InDividend % Divisor);
411
    }
412
 
413
    return_ACPI_STATUS (AE_OK);
414
}
415
 
416
ACPI_STATUS
417
AcpiUtDivide (
418
    UINT64                  InDividend,
419
    UINT64                  InDivisor,
420
    UINT64                  *OutQuotient,
421
    UINT64                  *OutRemainder)
422
{
423
    ACPI_FUNCTION_TRACE (UtDivide);
424
 
425
 
426
    /* Always check for a zero divisor */
427
 
428
    if (InDivisor == 0)
429
    {
430
        ACPI_ERROR ((AE_INFO, "Divide by zero"));
431
        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
432
    }
433
 
434
 
435
    /* Return only what was requested */
436
 
437
    if (OutQuotient)
438
    {
439
        *OutQuotient = InDividend / InDivisor;
440
    }
441
    if (OutRemainder)
442
    {
443
        *OutRemainder = InDividend % InDivisor;
444
    }
445
 
446
    return_ACPI_STATUS (AE_OK);
447
}
448
 
449
#endif
450