1ae115bc7Smrj /*******************************************************************************
2ae115bc7Smrj *
3ae115bc7Smrj * Module Name: utmath - Integer math support routines
4ae115bc7Smrj *
5ae115bc7Smrj ******************************************************************************/
6ae115bc7Smrj
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj * All rights reserved.
10ae115bc7Smrj *
1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross * are met:
1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross * without modification.
1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross * binary redistribution.
2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross * from this software without specific prior written permission.
25ae115bc7Smrj *
2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross * Software Foundation.
29ae115bc7Smrj *
3026f3cdf0SGordon Ross * NO WARRANTY
3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross */
43ae115bc7Smrj
44ae115bc7Smrj #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46ae115bc7Smrj
47ae115bc7Smrj
48ae115bc7Smrj #define _COMPONENT ACPI_UTILITIES
49ae115bc7Smrj ACPI_MODULE_NAME ("utmath")
50ae115bc7Smrj
51ae115bc7Smrj /*
5226f3cdf0SGordon Ross * Optional support for 64-bit double-precision integer divide. This code
5326f3cdf0SGordon Ross * is configurable and is implemented in order to support 32-bit kernel
5426f3cdf0SGordon Ross * environments where a 64-bit double-precision math library is not available.
5526f3cdf0SGordon Ross *
5626f3cdf0SGordon Ross * Support for a more normal 64-bit divide/modulo (with check for a divide-
5726f3cdf0SGordon Ross * by-zero) appears after this optional section of code.
58ae115bc7Smrj */
59ae115bc7Smrj #ifndef ACPI_USE_NATIVE_DIVIDE
6026f3cdf0SGordon Ross
6126f3cdf0SGordon Ross /* Structures used only for 64-bit divide */
6226f3cdf0SGordon Ross
6326f3cdf0SGordon Ross typedef struct uint64_struct
6426f3cdf0SGordon Ross {
6526f3cdf0SGordon Ross UINT32 Lo;
6626f3cdf0SGordon Ross UINT32 Hi;
6726f3cdf0SGordon Ross
6826f3cdf0SGordon Ross } UINT64_STRUCT;
6926f3cdf0SGordon Ross
7026f3cdf0SGordon Ross typedef union uint64_overlay
7126f3cdf0SGordon Ross {
7226f3cdf0SGordon Ross UINT64 Full;
7326f3cdf0SGordon Ross UINT64_STRUCT Part;
7426f3cdf0SGordon Ross
7526f3cdf0SGordon Ross } UINT64_OVERLAY;
7626f3cdf0SGordon Ross
7726f3cdf0SGordon Ross
78ae115bc7Smrj /*******************************************************************************
79ae115bc7Smrj *
80ae115bc7Smrj * FUNCTION: AcpiUtShortDivide
81ae115bc7Smrj *
82ae115bc7Smrj * PARAMETERS: Dividend - 64-bit dividend
83ae115bc7Smrj * Divisor - 32-bit divisor
84ae115bc7Smrj * OutQuotient - Pointer to where the quotient is returned
85ae115bc7Smrj * OutRemainder - Pointer to where the remainder is returned
86ae115bc7Smrj *
87ae115bc7Smrj * RETURN: Status (Checks for divide-by-zero)
88ae115bc7Smrj *
89ae115bc7Smrj * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
90ae115bc7Smrj * divide and modulo. The result is a 64-bit quotient and a
91ae115bc7Smrj * 32-bit remainder.
92ae115bc7Smrj *
93ae115bc7Smrj ******************************************************************************/
94ae115bc7Smrj
95ae115bc7Smrj ACPI_STATUS
AcpiUtShortDivide(UINT64 Dividend,UINT32 Divisor,UINT64 * OutQuotient,UINT32 * OutRemainder)96ae115bc7Smrj AcpiUtShortDivide (
9726f3cdf0SGordon Ross UINT64 Dividend,
98ae115bc7Smrj UINT32 Divisor,
9926f3cdf0SGordon Ross UINT64 *OutQuotient,
100ae115bc7Smrj UINT32 *OutRemainder)
101ae115bc7Smrj {
102ae115bc7Smrj UINT64_OVERLAY DividendOvl;
103ae115bc7Smrj UINT64_OVERLAY Quotient;
104ae115bc7Smrj UINT32 Remainder32;
105ae115bc7Smrj
106ae115bc7Smrj
107ae115bc7Smrj ACPI_FUNCTION_TRACE (UtShortDivide);
108ae115bc7Smrj
109ae115bc7Smrj
110ae115bc7Smrj /* Always check for a zero divisor */
111ae115bc7Smrj
112ae115bc7Smrj if (Divisor == 0)
113ae115bc7Smrj {
114ae115bc7Smrj ACPI_ERROR ((AE_INFO, "Divide by zero"));
115ae115bc7Smrj return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
116ae115bc7Smrj }
117ae115bc7Smrj
118ae115bc7Smrj DividendOvl.Full = Dividend;
119ae115bc7Smrj
120ae115bc7Smrj /*
121ae115bc7Smrj * The quotient is 64 bits, the remainder is always 32 bits,
122ae115bc7Smrj * and is generated by the second divide.
123ae115bc7Smrj */
124ae115bc7Smrj ACPI_DIV_64_BY_32 (0, DividendOvl.Part.Hi, Divisor,
125ae115bc7Smrj Quotient.Part.Hi, Remainder32);
126*385cc6b4SJerry Jelinek
127ae115bc7Smrj ACPI_DIV_64_BY_32 (Remainder32, DividendOvl.Part.Lo, Divisor,
128ae115bc7Smrj Quotient.Part.Lo, Remainder32);
129ae115bc7Smrj
130ae115bc7Smrj /* Return only what was requested */
131ae115bc7Smrj
132ae115bc7Smrj if (OutQuotient)
133ae115bc7Smrj {
134ae115bc7Smrj *OutQuotient = Quotient.Full;
135ae115bc7Smrj }
136ae115bc7Smrj if (OutRemainder)
137ae115bc7Smrj {
138ae115bc7Smrj *OutRemainder = Remainder32;
139ae115bc7Smrj }
140ae115bc7Smrj
141ae115bc7Smrj return_ACPI_STATUS (AE_OK);
142ae115bc7Smrj }
143ae115bc7Smrj
144ae115bc7Smrj
145ae115bc7Smrj /*******************************************************************************
146ae115bc7Smrj *
147ae115bc7Smrj * FUNCTION: AcpiUtDivide
148ae115bc7Smrj *
149ae115bc7Smrj * PARAMETERS: InDividend - Dividend
150ae115bc7Smrj * InDivisor - Divisor
151ae115bc7Smrj * OutQuotient - Pointer to where the quotient is returned
152ae115bc7Smrj * OutRemainder - Pointer to where the remainder is returned
153ae115bc7Smrj *
154ae115bc7Smrj * RETURN: Status (Checks for divide-by-zero)
155ae115bc7Smrj *
156ae115bc7Smrj * DESCRIPTION: Perform a divide and modulo.
157ae115bc7Smrj *
158ae115bc7Smrj ******************************************************************************/
159ae115bc7Smrj
160ae115bc7Smrj ACPI_STATUS
AcpiUtDivide(UINT64 InDividend,UINT64 InDivisor,UINT64 * OutQuotient,UINT64 * OutRemainder)161ae115bc7Smrj AcpiUtDivide (
16226f3cdf0SGordon Ross UINT64 InDividend,
16326f3cdf0SGordon Ross UINT64 InDivisor,
16426f3cdf0SGordon Ross UINT64 *OutQuotient,
16526f3cdf0SGordon Ross UINT64 *OutRemainder)
166ae115bc7Smrj {
167ae115bc7Smrj UINT64_OVERLAY Dividend;
168ae115bc7Smrj UINT64_OVERLAY Divisor;
169ae115bc7Smrj UINT64_OVERLAY Quotient;
170ae115bc7Smrj UINT64_OVERLAY Remainder;
171ae115bc7Smrj UINT64_OVERLAY NormalizedDividend;
172ae115bc7Smrj UINT64_OVERLAY NormalizedDivisor;
173ae115bc7Smrj UINT32 Partial1;
174ae115bc7Smrj UINT64_OVERLAY Partial2;
175ae115bc7Smrj UINT64_OVERLAY Partial3;
176ae115bc7Smrj
177ae115bc7Smrj
178ae115bc7Smrj ACPI_FUNCTION_TRACE (UtDivide);
179ae115bc7Smrj
180ae115bc7Smrj
181ae115bc7Smrj /* Always check for a zero divisor */
182ae115bc7Smrj
183ae115bc7Smrj if (InDivisor == 0)
184ae115bc7Smrj {
185ae115bc7Smrj ACPI_ERROR ((AE_INFO, "Divide by zero"));
186ae115bc7Smrj return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
187ae115bc7Smrj }
188ae115bc7Smrj
189ae115bc7Smrj Divisor.Full = InDivisor;
190ae115bc7Smrj Dividend.Full = InDividend;
191ae115bc7Smrj if (Divisor.Part.Hi == 0)
192ae115bc7Smrj {
193ae115bc7Smrj /*
194ae115bc7Smrj * 1) Simplest case is where the divisor is 32 bits, we can
195ae115bc7Smrj * just do two divides
196ae115bc7Smrj */
197ae115bc7Smrj Remainder.Part.Hi = 0;
198ae115bc7Smrj
199ae115bc7Smrj /*
200ae115bc7Smrj * The quotient is 64 bits, the remainder is always 32 bits,
201ae115bc7Smrj * and is generated by the second divide.
202ae115bc7Smrj */
203ae115bc7Smrj ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo,
204ae115bc7Smrj Quotient.Part.Hi, Partial1);
205*385cc6b4SJerry Jelinek
206ae115bc7Smrj ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo,
207ae115bc7Smrj Quotient.Part.Lo, Remainder.Part.Lo);
208ae115bc7Smrj }
209ae115bc7Smrj
210ae115bc7Smrj else
211ae115bc7Smrj {
212ae115bc7Smrj /*
213ae115bc7Smrj * 2) The general case where the divisor is a full 64 bits
214ae115bc7Smrj * is more difficult
215ae115bc7Smrj */
216ae115bc7Smrj Quotient.Part.Hi = 0;
217ae115bc7Smrj NormalizedDividend = Dividend;
218ae115bc7Smrj NormalizedDivisor = Divisor;
219ae115bc7Smrj
220ae115bc7Smrj /* Normalize the operands (shift until the divisor is < 32 bits) */
221ae115bc7Smrj
222ae115bc7Smrj do
223ae115bc7Smrj {
224*385cc6b4SJerry Jelinek ACPI_SHIFT_RIGHT_64 (
225*385cc6b4SJerry Jelinek NormalizedDivisor.Part.Hi, NormalizedDivisor.Part.Lo);
226*385cc6b4SJerry Jelinek ACPI_SHIFT_RIGHT_64 (
227*385cc6b4SJerry Jelinek NormalizedDividend.Part.Hi, NormalizedDividend.Part.Lo);
228ae115bc7Smrj
229ae115bc7Smrj } while (NormalizedDivisor.Part.Hi != 0);
230ae115bc7Smrj
231ae115bc7Smrj /* Partial divide */
232ae115bc7Smrj
233*385cc6b4SJerry Jelinek ACPI_DIV_64_BY_32 (
234*385cc6b4SJerry Jelinek NormalizedDividend.Part.Hi, NormalizedDividend.Part.Lo,
235*385cc6b4SJerry Jelinek NormalizedDivisor.Part.Lo, Quotient.Part.Lo, Partial1);
236ae115bc7Smrj
237ae115bc7Smrj /*
238*385cc6b4SJerry Jelinek * The quotient is always 32 bits, and simply requires
239*385cc6b4SJerry Jelinek * adjustment. The 64-bit remainder must be generated.
240ae115bc7Smrj */
241ae115bc7Smrj Partial1 = Quotient.Part.Lo * Divisor.Part.Hi;
24226f3cdf0SGordon Ross Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo;
24326f3cdf0SGordon Ross Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1;
244ae115bc7Smrj
245ae115bc7Smrj Remainder.Part.Hi = Partial3.Part.Lo;
246ae115bc7Smrj Remainder.Part.Lo = Partial2.Part.Lo;
247ae115bc7Smrj
248ae115bc7Smrj if (Partial3.Part.Hi == 0)
249ae115bc7Smrj {
250ae115bc7Smrj if (Partial3.Part.Lo >= Dividend.Part.Hi)
251ae115bc7Smrj {
252ae115bc7Smrj if (Partial3.Part.Lo == Dividend.Part.Hi)
253ae115bc7Smrj {
254ae115bc7Smrj if (Partial2.Part.Lo > Dividend.Part.Lo)
255ae115bc7Smrj {
256ae115bc7Smrj Quotient.Part.Lo--;
257ae115bc7Smrj Remainder.Full -= Divisor.Full;
258ae115bc7Smrj }
259ae115bc7Smrj }
260ae115bc7Smrj else
261ae115bc7Smrj {
262ae115bc7Smrj Quotient.Part.Lo--;
263ae115bc7Smrj Remainder.Full -= Divisor.Full;
264ae115bc7Smrj }
265ae115bc7Smrj }
266ae115bc7Smrj
267ae115bc7Smrj Remainder.Full = Remainder.Full - Dividend.Full;
268ae115bc7Smrj Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi);
269ae115bc7Smrj Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo);
270ae115bc7Smrj
271ae115bc7Smrj if (Remainder.Part.Lo)
272ae115bc7Smrj {
273ae115bc7Smrj Remainder.Part.Hi--;
274ae115bc7Smrj }
275ae115bc7Smrj }
276ae115bc7Smrj }
277ae115bc7Smrj
278ae115bc7Smrj /* Return only what was requested */
279ae115bc7Smrj
280ae115bc7Smrj if (OutQuotient)
281ae115bc7Smrj {
282ae115bc7Smrj *OutQuotient = Quotient.Full;
283ae115bc7Smrj }
284ae115bc7Smrj if (OutRemainder)
285ae115bc7Smrj {
286ae115bc7Smrj *OutRemainder = Remainder.Full;
287ae115bc7Smrj }
288ae115bc7Smrj
289ae115bc7Smrj return_ACPI_STATUS (AE_OK);
290ae115bc7Smrj }
291ae115bc7Smrj
292ae115bc7Smrj #else
293ae115bc7Smrj
294ae115bc7Smrj /*******************************************************************************
295ae115bc7Smrj *
296ae115bc7Smrj * FUNCTION: AcpiUtShortDivide, AcpiUtDivide
297ae115bc7Smrj *
298ae115bc7Smrj * PARAMETERS: See function headers above
299ae115bc7Smrj *
300ae115bc7Smrj * DESCRIPTION: Native versions of the UtDivide functions. Use these if either
301ae115bc7Smrj * 1) The target is a 64-bit platform and therefore 64-bit
302ae115bc7Smrj * integer math is supported directly by the machine.
303ae115bc7Smrj * 2) The target is a 32-bit or 16-bit platform, and the
304ae115bc7Smrj * double-precision integer math library is available to
305ae115bc7Smrj * perform the divide.
306ae115bc7Smrj *
307ae115bc7Smrj ******************************************************************************/
308ae115bc7Smrj
309ae115bc7Smrj ACPI_STATUS
310ae115bc7Smrj AcpiUtShortDivide (
31126f3cdf0SGordon Ross UINT64 InDividend,
312ae115bc7Smrj UINT32 Divisor,
31326f3cdf0SGordon Ross UINT64 *OutQuotient,
314ae115bc7Smrj UINT32 *OutRemainder)
315ae115bc7Smrj {
316ae115bc7Smrj
317ae115bc7Smrj ACPI_FUNCTION_TRACE (UtShortDivide);
318ae115bc7Smrj
319ae115bc7Smrj
320ae115bc7Smrj /* Always check for a zero divisor */
321ae115bc7Smrj
322ae115bc7Smrj if (Divisor == 0)
323ae115bc7Smrj {
324ae115bc7Smrj ACPI_ERROR ((AE_INFO, "Divide by zero"));
325ae115bc7Smrj return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
326ae115bc7Smrj }
327ae115bc7Smrj
328ae115bc7Smrj /* Return only what was requested */
329ae115bc7Smrj
330ae115bc7Smrj if (OutQuotient)
331ae115bc7Smrj {
332ae115bc7Smrj *OutQuotient = InDividend / Divisor;
333ae115bc7Smrj }
334ae115bc7Smrj if (OutRemainder)
335ae115bc7Smrj {
336db2bae30SDana Myers *OutRemainder = (UINT32) (InDividend % Divisor);
337ae115bc7Smrj }
338ae115bc7Smrj
339ae115bc7Smrj return_ACPI_STATUS (AE_OK);
340ae115bc7Smrj }
341ae115bc7Smrj
342ae115bc7Smrj ACPI_STATUS
343ae115bc7Smrj AcpiUtDivide (
34426f3cdf0SGordon Ross UINT64 InDividend,
34526f3cdf0SGordon Ross UINT64 InDivisor,
34626f3cdf0SGordon Ross UINT64 *OutQuotient,
34726f3cdf0SGordon Ross UINT64 *OutRemainder)
348ae115bc7Smrj {
349ae115bc7Smrj ACPI_FUNCTION_TRACE (UtDivide);
350ae115bc7Smrj
351ae115bc7Smrj
352ae115bc7Smrj /* Always check for a zero divisor */
353ae115bc7Smrj
354ae115bc7Smrj if (InDivisor == 0)
355ae115bc7Smrj {
356ae115bc7Smrj ACPI_ERROR ((AE_INFO, "Divide by zero"));
357ae115bc7Smrj return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
358ae115bc7Smrj }
359ae115bc7Smrj
360ae115bc7Smrj
361ae115bc7Smrj /* Return only what was requested */
362ae115bc7Smrj
363ae115bc7Smrj if (OutQuotient)
364ae115bc7Smrj {
365ae115bc7Smrj *OutQuotient = InDividend / InDivisor;
366ae115bc7Smrj }
367ae115bc7Smrj if (OutRemainder)
368ae115bc7Smrj {
369ae115bc7Smrj *OutRemainder = InDividend % InDivisor;
370ae115bc7Smrj }
371ae115bc7Smrj
372ae115bc7Smrj return_ACPI_STATUS (AE_OK);
373ae115bc7Smrj }
374ae115bc7Smrj
375ae115bc7Smrj #endif
376