184493Smsmith/*******************************************************************************
284493Smsmith *
384493Smsmith * Module Name: utmath - Integer math support routines
484493Smsmith *
584493Smsmith ******************************************************************************/
684493Smsmith
7316303Sjkim/******************************************************************************
8316303Sjkim *
9316303Sjkim * 1. Copyright Notice
10316303Sjkim *
11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
1284493Smsmith * All rights reserved.
1384493Smsmith *
14316303Sjkim * 2. License
15316303Sjkim *
16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
17316303Sjkim * rights. You may have additional license terms from the party that provided
18316303Sjkim * you this software, covering your right to use that party's intellectual
19316303Sjkim * property rights.
20316303Sjkim *
21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an
23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy,
25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered
26316303Sjkim * Code in any form, with the right to sublicense such rights; and
27316303Sjkim *
28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29316303Sjkim * license (with the right to sublicense), under only those claims of Intel
30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof
32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright
33316303Sjkim * license, and in no event shall the patent license extend to any additions
34316303Sjkim * to or modifications of the Original Intel Code. No other license or right
35316303Sjkim * is granted directly or by implication, estoppel or otherwise;
36316303Sjkim *
37316303Sjkim * The above copyright and patent license is granted only if the following
38316303Sjkim * conditions are met:
39316303Sjkim *
40316303Sjkim * 3. Conditions
41316303Sjkim *
42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43316303Sjkim * Redistribution of source code of any substantial portion of the Covered
44316303Sjkim * Code or modification with rights to further distribute source must include
45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions,
46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition,
47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to
48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered
49316303Sjkim * Code and the date of any change. Licensee must include in that file the
50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee
51316303Sjkim * must include a prominent statement that the modification is derived,
52316303Sjkim * directly or indirectly, from Original Intel Code.
53316303Sjkim *
54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55316303Sjkim * Redistribution of source code of any substantial portion of the Covered
56316303Sjkim * Code or modification without rights to further distribute source must
57316303Sjkim * include the following Disclaimer and Export Compliance provision in the
58316303Sjkim * documentation and/or other materials provided with distribution. In
59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any
60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the
61316303Sjkim * license from Licensee to its licensee is limited to the intellectual
62316303Sjkim * property embodied in the software Licensee provides to its licensee, and
63316303Sjkim * not to intellectual property embodied in modifications its licensee may
64316303Sjkim * make.
65316303Sjkim *
66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the
68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
69316303Sjkim * provision in the documentation and/or other materials provided with the
70316303Sjkim * distribution.
71316303Sjkim *
72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
73316303Sjkim * Intel Code.
74316303Sjkim *
75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
77316303Sjkim * other dealings in products derived from or relating to the Covered Code
78316303Sjkim * without prior written authorization from Intel.
79316303Sjkim *
80316303Sjkim * 4. Disclaimer and Export Compliance
81316303Sjkim *
82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88316303Sjkim * PARTICULAR PURPOSE.
89316303Sjkim *
90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97316303Sjkim * LIMITED REMEDY.
98316303Sjkim *
99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
100316303Sjkim * software or system incorporating such software without first obtaining any
101316303Sjkim * required license or other approval from the U. S. Department of Commerce or
102316303Sjkim * any other agency or department of the United States Government. In the
103316303Sjkim * event Licensee exports any such software from the United States or
104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall
105316303Sjkim * ensure that the distribution and export/re-export of the software is in
106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process,
109316303Sjkim * software, or service, directly or indirectly, to any country for which the
110316303Sjkim * United States government or any agency thereof requires an export license,
111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining
112316303Sjkim * such license, approval or letter.
113316303Sjkim *
114316303Sjkim *****************************************************************************
115316303Sjkim *
116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
117316303Sjkim * following license:
118316303Sjkim *
119217365Sjkim * Redistribution and use in source and binary forms, with or without
120217365Sjkim * modification, are permitted provided that the following conditions
121217365Sjkim * are met:
122217365Sjkim * 1. Redistributions of source code must retain the above copyright
123217365Sjkim *    notice, this list of conditions, and the following disclaimer,
124217365Sjkim *    without modification.
125217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
127217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
128217365Sjkim *    including a substantially similar Disclaimer requirement for further
129217365Sjkim *    binary redistribution.
130217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
131217365Sjkim *    of any contributors may be used to endorse or promote products derived
132217365Sjkim *    from this software without specific prior written permission.
13384493Smsmith *
134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145316303Sjkim *
146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
147217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
148217365Sjkim * Software Foundation.
14984493Smsmith *
150316303Sjkim *****************************************************************************/
15184493Smsmith
152193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
153193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
15484493Smsmith
15584493Smsmith
15684493Smsmith#define _COMPONENT          ACPI_UTILITIES
15791116Smsmith        ACPI_MODULE_NAME    ("utmath")
15884493Smsmith
159212761Sjkim/* Structures used only for 64-bit divide */
160212761Sjkim
161212761Sjkimtypedef struct uint64_struct
162212761Sjkim{
163212761Sjkim    UINT32                          Lo;
164212761Sjkim    UINT32                          Hi;
165212761Sjkim
166212761Sjkim} UINT64_STRUCT;
167212761Sjkim
168212761Sjkimtypedef union uint64_overlay
169212761Sjkim{
170212761Sjkim    UINT64                          Full;
171212761Sjkim    UINT64_STRUCT                   Part;
172212761Sjkim
173212761Sjkim} UINT64_OVERLAY;
174212761Sjkim
175322877Sjkim/*
176322877Sjkim * Optional support for 64-bit double-precision integer multiply and shift.
177322877Sjkim * This code is configurable and is implemented in order to support 32-bit
178322877Sjkim * kernel environments where a 64-bit double-precision math library is not
179322877Sjkim * available.
180322877Sjkim */
181322877Sjkim#ifndef ACPI_USE_NATIVE_MATH64
182212761Sjkim
18384493Smsmith/*******************************************************************************
18484493Smsmith *
185322877Sjkim * FUNCTION:    AcpiUtShortMultiply
186322877Sjkim *
187322877Sjkim * PARAMETERS:  Multiplicand        - 64-bit multiplicand
188322877Sjkim *              Multiplier          - 32-bit multiplier
189322877Sjkim *              OutProduct          - Pointer to where the product is returned
190322877Sjkim *
191322877Sjkim * DESCRIPTION: Perform a short multiply.
192322877Sjkim *
193322877Sjkim ******************************************************************************/
194322877Sjkim
195322877SjkimACPI_STATUS
196322877SjkimAcpiUtShortMultiply (
197322877Sjkim    UINT64                  Multiplicand,
198322877Sjkim    UINT32                  Multiplier,
199322877Sjkim    UINT64                  *OutProduct)
200322877Sjkim{
201322877Sjkim    UINT64_OVERLAY          MultiplicandOvl;
202322877Sjkim    UINT64_OVERLAY          Product;
203322877Sjkim    UINT32                  Carry32;
204322877Sjkim
205322877Sjkim
206322877Sjkim    ACPI_FUNCTION_TRACE (UtShortMultiply);
207322877Sjkim
208322877Sjkim
209322877Sjkim    MultiplicandOvl.Full = Multiplicand;
210322877Sjkim
211322877Sjkim    /*
212322877Sjkim     * The Product is 64 bits, the carry is always 32 bits,
213322877Sjkim     * and is generated by the second multiply.
214322877Sjkim     */
215322877Sjkim    ACPI_MUL_64_BY_32 (0, MultiplicandOvl.Part.Hi, Multiplier,
216322877Sjkim        Product.Part.Hi, Carry32);
217322877Sjkim
218322877Sjkim    ACPI_MUL_64_BY_32 (0, MultiplicandOvl.Part.Lo, Multiplier,
219322877Sjkim        Product.Part.Lo, Carry32);
220322877Sjkim
221322877Sjkim    Product.Part.Hi += Carry32;
222322877Sjkim
223322877Sjkim    /* Return only what was requested */
224322877Sjkim
225322877Sjkim    if (OutProduct)
226322877Sjkim    {
227322877Sjkim        *OutProduct = Product.Full;
228322877Sjkim    }
229322877Sjkim
230322877Sjkim    return_ACPI_STATUS (AE_OK);
231322877Sjkim}
232322877Sjkim
233322877Sjkim
234322877Sjkim/*******************************************************************************
235322877Sjkim *
236322877Sjkim * FUNCTION:    AcpiUtShortShiftLeft
237322877Sjkim *
238322877Sjkim * PARAMETERS:  Operand             - 64-bit shift operand
239322877Sjkim *              Count               - 32-bit shift count
240322877Sjkim *              OutResult           - Pointer to where the result is returned
241322877Sjkim *
242322877Sjkim * DESCRIPTION: Perform a short left shift.
243322877Sjkim *
244322877Sjkim ******************************************************************************/
245322877Sjkim
246322877SjkimACPI_STATUS
247322877SjkimAcpiUtShortShiftLeft (
248322877Sjkim    UINT64                  Operand,
249322877Sjkim    UINT32                  Count,
250322877Sjkim    UINT64                  *OutResult)
251322877Sjkim{
252322877Sjkim    UINT64_OVERLAY          OperandOvl;
253322877Sjkim
254322877Sjkim
255322877Sjkim    ACPI_FUNCTION_TRACE (UtShortShiftLeft);
256322877Sjkim
257322877Sjkim
258322877Sjkim    OperandOvl.Full = Operand;
259322877Sjkim
260322877Sjkim    if ((Count & 63) >= 32)
261322877Sjkim    {
262322877Sjkim        OperandOvl.Part.Hi = OperandOvl.Part.Lo;
263327557Sjkim        OperandOvl.Part.Lo = 0;
264322877Sjkim        Count = (Count & 63) - 32;
265322877Sjkim    }
266322877Sjkim    ACPI_SHIFT_LEFT_64_BY_32 (OperandOvl.Part.Hi,
267322877Sjkim        OperandOvl.Part.Lo, Count);
268322877Sjkim
269322877Sjkim    /* Return only what was requested */
270322877Sjkim
271322877Sjkim    if (OutResult)
272322877Sjkim    {
273322877Sjkim        *OutResult = OperandOvl.Full;
274322877Sjkim    }
275322877Sjkim
276322877Sjkim    return_ACPI_STATUS (AE_OK);
277322877Sjkim}
278322877Sjkim
279322877Sjkim/*******************************************************************************
280322877Sjkim *
281322877Sjkim * FUNCTION:    AcpiUtShortShiftRight
282322877Sjkim *
283322877Sjkim * PARAMETERS:  Operand             - 64-bit shift operand
284322877Sjkim *              Count               - 32-bit shift count
285322877Sjkim *              OutResult           - Pointer to where the result is returned
286322877Sjkim *
287322877Sjkim * DESCRIPTION: Perform a short right shift.
288322877Sjkim *
289322877Sjkim ******************************************************************************/
290322877Sjkim
291322877SjkimACPI_STATUS
292322877SjkimAcpiUtShortShiftRight (
293322877Sjkim    UINT64                  Operand,
294322877Sjkim    UINT32                  Count,
295322877Sjkim    UINT64                  *OutResult)
296322877Sjkim{
297322877Sjkim    UINT64_OVERLAY          OperandOvl;
298322877Sjkim
299322877Sjkim
300322877Sjkim    ACPI_FUNCTION_TRACE (UtShortShiftRight);
301322877Sjkim
302322877Sjkim
303322877Sjkim    OperandOvl.Full = Operand;
304322877Sjkim
305322877Sjkim    if ((Count & 63) >= 32)
306322877Sjkim    {
307322877Sjkim        OperandOvl.Part.Lo = OperandOvl.Part.Hi;
308327557Sjkim        OperandOvl.Part.Hi = 0;
309322877Sjkim        Count = (Count & 63) - 32;
310322877Sjkim    }
311322877Sjkim    ACPI_SHIFT_RIGHT_64_BY_32 (OperandOvl.Part.Hi,
312322877Sjkim        OperandOvl.Part.Lo, Count);
313322877Sjkim
314322877Sjkim    /* Return only what was requested */
315322877Sjkim
316322877Sjkim    if (OutResult)
317322877Sjkim    {
318322877Sjkim        *OutResult = OperandOvl.Full;
319322877Sjkim    }
320322877Sjkim
321322877Sjkim    return_ACPI_STATUS (AE_OK);
322322877Sjkim}
323322877Sjkim#else
324322877Sjkim
325322877Sjkim/*******************************************************************************
326322877Sjkim *
327322877Sjkim * FUNCTION:    AcpiUtShortMultiply
328322877Sjkim *
329322877Sjkim * PARAMETERS:  See function headers above
330322877Sjkim *
331322877Sjkim * DESCRIPTION: Native version of the UtShortMultiply function.
332322877Sjkim *
333322877Sjkim ******************************************************************************/
334322877Sjkim
335322877SjkimACPI_STATUS
336322877SjkimAcpiUtShortMultiply (
337322877Sjkim    UINT64                  Multiplicand,
338322877Sjkim    UINT32                  Multiplier,
339322877Sjkim    UINT64                  *OutProduct)
340322877Sjkim{
341322877Sjkim
342322877Sjkim    ACPI_FUNCTION_TRACE (UtShortMultiply);
343322877Sjkim
344322877Sjkim
345322877Sjkim    /* Return only what was requested */
346322877Sjkim
347322877Sjkim    if (OutProduct)
348322877Sjkim    {
349322877Sjkim        *OutProduct = Multiplicand * Multiplier;
350322877Sjkim    }
351322877Sjkim
352322877Sjkim    return_ACPI_STATUS (AE_OK);
353322877Sjkim}
354322877Sjkim
355322877Sjkim/*******************************************************************************
356322877Sjkim *
357322877Sjkim * FUNCTION:    AcpiUtShortShiftLeft
358322877Sjkim *
359322877Sjkim * PARAMETERS:  See function headers above
360322877Sjkim *
361322877Sjkim * DESCRIPTION: Native version of the UtShortShiftLeft function.
362322877Sjkim *
363322877Sjkim ******************************************************************************/
364322877Sjkim
365322877SjkimACPI_STATUS
366322877SjkimAcpiUtShortShiftLeft (
367322877Sjkim    UINT64                  Operand,
368322877Sjkim    UINT32                  Count,
369322877Sjkim    UINT64                  *OutResult)
370322877Sjkim{
371322877Sjkim
372322877Sjkim    ACPI_FUNCTION_TRACE (UtShortShiftLeft);
373322877Sjkim
374322877Sjkim
375322877Sjkim    /* Return only what was requested */
376322877Sjkim
377322877Sjkim    if (OutResult)
378322877Sjkim    {
379322877Sjkim        *OutResult = Operand << Count;
380322877Sjkim    }
381322877Sjkim
382322877Sjkim    return_ACPI_STATUS (AE_OK);
383322877Sjkim}
384322877Sjkim
385322877Sjkim/*******************************************************************************
386322877Sjkim *
387322877Sjkim * FUNCTION:    AcpiUtShortShiftRight
388322877Sjkim *
389322877Sjkim * PARAMETERS:  See function headers above
390322877Sjkim *
391322877Sjkim * DESCRIPTION: Native version of the UtShortShiftRight function.
392322877Sjkim *
393322877Sjkim ******************************************************************************/
394322877Sjkim
395322877SjkimACPI_STATUS
396322877SjkimAcpiUtShortShiftRight (
397322877Sjkim    UINT64                  Operand,
398322877Sjkim    UINT32                  Count,
399322877Sjkim    UINT64                  *OutResult)
400322877Sjkim{
401322877Sjkim
402322877Sjkim    ACPI_FUNCTION_TRACE (UtShortShiftRight);
403322877Sjkim
404322877Sjkim
405322877Sjkim    /* Return only what was requested */
406322877Sjkim
407322877Sjkim    if (OutResult)
408322877Sjkim    {
409322877Sjkim        *OutResult = Operand >> Count;
410322877Sjkim    }
411322877Sjkim
412322877Sjkim    return_ACPI_STATUS (AE_OK);
413322877Sjkim}
414322877Sjkim#endif
415322877Sjkim
416322877Sjkim/*
417322877Sjkim * Optional support for 64-bit double-precision integer divide. This code
418322877Sjkim * is configurable and is implemented in order to support 32-bit kernel
419322877Sjkim * environments where a 64-bit double-precision math library is not available.
420322877Sjkim *
421322877Sjkim * Support for a more normal 64-bit divide/modulo (with check for a divide-
422322877Sjkim * by-zero) appears after this optional section of code.
423322877Sjkim */
424322877Sjkim#ifndef ACPI_USE_NATIVE_DIVIDE
425322877Sjkim
426322877Sjkim
427322877Sjkim/*******************************************************************************
428322877Sjkim *
42984493Smsmith * FUNCTION:    AcpiUtShortDivide
43084493Smsmith *
431138287Smarks * PARAMETERS:  Dividend            - 64-bit dividend
43284493Smsmith *              Divisor             - 32-bit divisor
43384493Smsmith *              OutQuotient         - Pointer to where the quotient is returned
43484493Smsmith *              OutRemainder        - Pointer to where the remainder is returned
43584493Smsmith *
43684493Smsmith * RETURN:      Status (Checks for divide-by-zero)
43784493Smsmith *
43884493Smsmith * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
439241973Sjkim *              divide and modulo. The result is a 64-bit quotient and a
44084493Smsmith *              32-bit remainder.
44184493Smsmith *
44284493Smsmith ******************************************************************************/
44384493Smsmith
44484493SmsmithACPI_STATUS
44584493SmsmithAcpiUtShortDivide (
446202771Sjkim    UINT64                  Dividend,
44784493Smsmith    UINT32                  Divisor,
448202771Sjkim    UINT64                  *OutQuotient,
44984493Smsmith    UINT32                  *OutRemainder)
45084493Smsmith{
451138287Smarks    UINT64_OVERLAY          DividendOvl;
45284493Smsmith    UINT64_OVERLAY          Quotient;
45384493Smsmith    UINT32                  Remainder32;
45484493Smsmith
45584493Smsmith
456167802Sjkim    ACPI_FUNCTION_TRACE (UtShortDivide);
45784493Smsmith
45884493Smsmith
45984493Smsmith    /* Always check for a zero divisor */
46084493Smsmith
46184493Smsmith    if (Divisor == 0)
46284493Smsmith    {
463167802Sjkim        ACPI_ERROR ((AE_INFO, "Divide by zero"));
46484493Smsmith        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
46584493Smsmith    }
46684493Smsmith
467138287Smarks    DividendOvl.Full = Dividend;
468138287Smarks
46984493Smsmith    /*
47084493Smsmith     * The quotient is 64 bits, the remainder is always 32 bits,
47184493Smsmith     * and is generated by the second divide.
47284493Smsmith     */
473138287Smarks    ACPI_DIV_64_BY_32 (0, DividendOvl.Part.Hi, Divisor,
474298714Sjkim        Quotient.Part.Hi, Remainder32);
475298714Sjkim
476138287Smarks    ACPI_DIV_64_BY_32 (Remainder32, DividendOvl.Part.Lo, Divisor,
477298714Sjkim        Quotient.Part.Lo, Remainder32);
47884493Smsmith
47984493Smsmith    /* Return only what was requested */
48084493Smsmith
48184493Smsmith    if (OutQuotient)
48284493Smsmith    {
48384493Smsmith        *OutQuotient = Quotient.Full;
48484493Smsmith    }
48584493Smsmith    if (OutRemainder)
48684493Smsmith    {
48784493Smsmith        *OutRemainder = Remainder32;
48884493Smsmith    }
48984493Smsmith
49084493Smsmith    return_ACPI_STATUS (AE_OK);
49184493Smsmith}
49284493Smsmith
49384493Smsmith
49484493Smsmith/*******************************************************************************
49584493Smsmith *
49684493Smsmith * FUNCTION:    AcpiUtDivide
49784493Smsmith *
498138287Smarks * PARAMETERS:  InDividend          - Dividend
499138287Smarks *              InDivisor           - Divisor
50084493Smsmith *              OutQuotient         - Pointer to where the quotient is returned
50184493Smsmith *              OutRemainder        - Pointer to where the remainder is returned
50284493Smsmith *
50384493Smsmith * RETURN:      Status (Checks for divide-by-zero)
50484493Smsmith *
50584493Smsmith * DESCRIPTION: Perform a divide and modulo.
50684493Smsmith *
50784493Smsmith ******************************************************************************/
50884493Smsmith
50984493SmsmithACPI_STATUS
51084493SmsmithAcpiUtDivide (
511202771Sjkim    UINT64                  InDividend,
512202771Sjkim    UINT64                  InDivisor,
513202771Sjkim    UINT64                  *OutQuotient,
514202771Sjkim    UINT64                  *OutRemainder)
51584493Smsmith{
51684493Smsmith    UINT64_OVERLAY          Dividend;
51784493Smsmith    UINT64_OVERLAY          Divisor;
51884493Smsmith    UINT64_OVERLAY          Quotient;
51984493Smsmith    UINT64_OVERLAY          Remainder;
52084493Smsmith    UINT64_OVERLAY          NormalizedDividend;
52184493Smsmith    UINT64_OVERLAY          NormalizedDivisor;
52284493Smsmith    UINT32                  Partial1;
52384493Smsmith    UINT64_OVERLAY          Partial2;
52484493Smsmith    UINT64_OVERLAY          Partial3;
52584493Smsmith
52684493Smsmith
527167802Sjkim    ACPI_FUNCTION_TRACE (UtDivide);
52884493Smsmith
52984493Smsmith
53084493Smsmith    /* Always check for a zero divisor */
53184493Smsmith
532138287Smarks    if (InDivisor == 0)
53384493Smsmith    {
534167802Sjkim        ACPI_ERROR ((AE_INFO, "Divide by zero"));
53584493Smsmith        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
53684493Smsmith    }
53784493Smsmith
538138287Smarks    Divisor.Full  = InDivisor;
539138287Smarks    Dividend.Full = InDividend;
54084493Smsmith    if (Divisor.Part.Hi == 0)
54184493Smsmith    {
54284493Smsmith        /*
54384493Smsmith         * 1) Simplest case is where the divisor is 32 bits, we can
54484493Smsmith         * just do two divides
54584493Smsmith         */
54684493Smsmith        Remainder.Part.Hi = 0;
54784493Smsmith
54884493Smsmith        /*
54984493Smsmith         * The quotient is 64 bits, the remainder is always 32 bits,
55084493Smsmith         * and is generated by the second divide.
55184493Smsmith         */
55287031Smsmith        ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo,
553298714Sjkim            Quotient.Part.Hi, Partial1);
554298714Sjkim
55587031Smsmith        ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo,
556298714Sjkim            Quotient.Part.Lo, Remainder.Part.Lo);
55784493Smsmith    }
55884493Smsmith
55984493Smsmith    else
56084493Smsmith    {
56184493Smsmith        /*
56284493Smsmith         * 2) The general case where the divisor is a full 64 bits
56384493Smsmith         * is more difficult
56484493Smsmith         */
56584493Smsmith        Quotient.Part.Hi   = 0;
56684493Smsmith        NormalizedDividend = Dividend;
56784493Smsmith        NormalizedDivisor  = Divisor;
56884493Smsmith
56984493Smsmith        /* Normalize the operands (shift until the divisor is < 32 bits) */
57084493Smsmith
57184493Smsmith        do
57284493Smsmith        {
573298714Sjkim            ACPI_SHIFT_RIGHT_64 (
574298714Sjkim                NormalizedDivisor.Part.Hi, NormalizedDivisor.Part.Lo);
575298714Sjkim            ACPI_SHIFT_RIGHT_64 (
576298714Sjkim                NormalizedDividend.Part.Hi, NormalizedDividend.Part.Lo);
57784493Smsmith
57884493Smsmith        } while (NormalizedDivisor.Part.Hi != 0);
57984493Smsmith
58084493Smsmith        /* Partial divide */
58184493Smsmith
582298714Sjkim        ACPI_DIV_64_BY_32 (
583298714Sjkim            NormalizedDividend.Part.Hi, NormalizedDividend.Part.Lo,
584298714Sjkim            NormalizedDivisor.Part.Lo, Quotient.Part.Lo, Partial1);
58584493Smsmith
58684493Smsmith        /*
587298714Sjkim         * The quotient is always 32 bits, and simply requires
588298714Sjkim         * adjustment. The 64-bit remainder must be generated.
58984493Smsmith         */
590298714Sjkim        Partial1 = Quotient.Part.Lo * Divisor.Part.Hi;
591202771Sjkim        Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo;
592202771Sjkim        Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1;
59384493Smsmith
59484493Smsmith        Remainder.Part.Hi = Partial3.Part.Lo;
59584493Smsmith        Remainder.Part.Lo = Partial2.Part.Lo;
59684493Smsmith
59784493Smsmith        if (Partial3.Part.Hi == 0)
59884493Smsmith        {
59984493Smsmith            if (Partial3.Part.Lo >= Dividend.Part.Hi)
60084493Smsmith            {
60184493Smsmith                if (Partial3.Part.Lo == Dividend.Part.Hi)
60284493Smsmith                {
60384493Smsmith                    if (Partial2.Part.Lo > Dividend.Part.Lo)
60484493Smsmith                    {
60584493Smsmith                        Quotient.Part.Lo--;
60684493Smsmith                        Remainder.Full -= Divisor.Full;
60784493Smsmith                    }
60884493Smsmith                }
60984493Smsmith                else
61084493Smsmith                {
61184493Smsmith                    Quotient.Part.Lo--;
61284493Smsmith                    Remainder.Full -= Divisor.Full;
61384493Smsmith                }
61484493Smsmith            }
61584493Smsmith
616298714Sjkim            Remainder.Full = Remainder.Full - Dividend.Full;
61799679Siwasaki            Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi);
61899679Siwasaki            Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo);
61984493Smsmith
62084493Smsmith            if (Remainder.Part.Lo)
62184493Smsmith            {
62284493Smsmith                Remainder.Part.Hi--;
62384493Smsmith            }
62484493Smsmith        }
62584493Smsmith    }
62684493Smsmith
62784493Smsmith    /* Return only what was requested */
62884493Smsmith
62984493Smsmith    if (OutQuotient)
63084493Smsmith    {
63184493Smsmith        *OutQuotient = Quotient.Full;
63284493Smsmith    }
63384493Smsmith    if (OutRemainder)
63484493Smsmith    {
63584493Smsmith        *OutRemainder = Remainder.Full;
63684493Smsmith    }
63784493Smsmith
63884493Smsmith    return_ACPI_STATUS (AE_OK);
63984493Smsmith}
64084493Smsmith
64184493Smsmith#else
64284493Smsmith
64384493Smsmith/*******************************************************************************
64484493Smsmith *
64584493Smsmith * FUNCTION:    AcpiUtShortDivide, AcpiUtDivide
64684493Smsmith *
647151937Sjkim * PARAMETERS:  See function headers above
648151937Sjkim *
64984493Smsmith * DESCRIPTION: Native versions of the UtDivide functions. Use these if either
65084493Smsmith *              1) The target is a 64-bit platform and therefore 64-bit
65184493Smsmith *                 integer math is supported directly by the machine.
65287031Smsmith *              2) The target is a 32-bit or 16-bit platform, and the
65387031Smsmith *                 double-precision integer math library is available to
65484493Smsmith *                 perform the divide.
65584493Smsmith *
65684493Smsmith ******************************************************************************/
65784493Smsmith
65884493SmsmithACPI_STATUS
65984493SmsmithAcpiUtShortDivide (
660202771Sjkim    UINT64                  InDividend,
66184493Smsmith    UINT32                  Divisor,
662202771Sjkim    UINT64                  *OutQuotient,
66384493Smsmith    UINT32                  *OutRemainder)
66484493Smsmith{
66584493Smsmith
666167802Sjkim    ACPI_FUNCTION_TRACE (UtShortDivide);
66784493Smsmith
66884493Smsmith
66984493Smsmith    /* Always check for a zero divisor */
67084493Smsmith
67184493Smsmith    if (Divisor == 0)
67284493Smsmith    {
673167802Sjkim        ACPI_ERROR ((AE_INFO, "Divide by zero"));
67484493Smsmith        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
67584493Smsmith    }
67684493Smsmith
67784493Smsmith    /* Return only what was requested */
67884493Smsmith
67984493Smsmith    if (OutQuotient)
68084493Smsmith    {
681138287Smarks        *OutQuotient = InDividend / Divisor;
68284493Smsmith    }
68384493Smsmith    if (OutRemainder)
68484493Smsmith    {
685193267Sjkim        *OutRemainder = (UINT32) (InDividend % Divisor);
68684493Smsmith    }
68784493Smsmith
68884493Smsmith    return_ACPI_STATUS (AE_OK);
68984493Smsmith}
69084493Smsmith
69184493SmsmithACPI_STATUS
69284493SmsmithAcpiUtDivide (
693202771Sjkim    UINT64                  InDividend,
694202771Sjkim    UINT64                  InDivisor,
695202771Sjkim    UINT64                  *OutQuotient,
696202771Sjkim    UINT64                  *OutRemainder)
69784493Smsmith{
698167802Sjkim    ACPI_FUNCTION_TRACE (UtDivide);
69984493Smsmith
70084493Smsmith
70184493Smsmith    /* Always check for a zero divisor */
70284493Smsmith
703138287Smarks    if (InDivisor == 0)
70484493Smsmith    {
705167802Sjkim        ACPI_ERROR ((AE_INFO, "Divide by zero"));
70684493Smsmith        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
70784493Smsmith    }
70884493Smsmith
70984493Smsmith
71084493Smsmith    /* Return only what was requested */
71184493Smsmith
71284493Smsmith    if (OutQuotient)
71384493Smsmith    {
714138287Smarks        *OutQuotient = InDividend / InDivisor;
71584493Smsmith    }
71684493Smsmith    if (OutRemainder)
71784493Smsmith    {
718138287Smarks        *OutRemainder = InDividend % InDivisor;
71984493Smsmith    }
72084493Smsmith
72185756Smsmith    return_ACPI_STATUS (AE_OK);
72284493Smsmith}
72384493Smsmith
72484493Smsmith#endif
725