xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/utmath.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: utmath - Integer math support routines
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  ******************************************************************************/
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define _COMPONENT          ACPI_UTILITIES
12*4882a593Smuzhiyun ACPI_MODULE_NAME("utmath")
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun /* Structures used only for 64-bit divide */
15*4882a593Smuzhiyun typedef struct uint64_struct {
16*4882a593Smuzhiyun 	u32 lo;
17*4882a593Smuzhiyun 	u32 hi;
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun } uint64_struct;
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun typedef union uint64_overlay {
22*4882a593Smuzhiyun 	u64 full;
23*4882a593Smuzhiyun 	struct uint64_struct part;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun } uint64_overlay;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun  * Optional support for 64-bit double-precision integer multiply and shift.
29*4882a593Smuzhiyun  * This code is configurable and is implemented in order to support 32-bit
30*4882a593Smuzhiyun  * kernel environments where a 64-bit double-precision math library is not
31*4882a593Smuzhiyun  * available.
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun #ifndef ACPI_USE_NATIVE_MATH64
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun /*******************************************************************************
36*4882a593Smuzhiyun  *
37*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_multiply
38*4882a593Smuzhiyun  *
39*4882a593Smuzhiyun  * PARAMETERS:  multiplicand        - 64-bit multiplicand
40*4882a593Smuzhiyun  *              multiplier          - 32-bit multiplier
41*4882a593Smuzhiyun  *              out_product         - Pointer to where the product is returned
42*4882a593Smuzhiyun  *
43*4882a593Smuzhiyun  * DESCRIPTION: Perform a short multiply.
44*4882a593Smuzhiyun  *
45*4882a593Smuzhiyun  ******************************************************************************/
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun acpi_status
acpi_ut_short_multiply(u64 multiplicand,u32 multiplier,u64 * out_product)48*4882a593Smuzhiyun acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	union uint64_overlay multiplicand_ovl;
51*4882a593Smuzhiyun 	union uint64_overlay product;
52*4882a593Smuzhiyun 	u32 carry32;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_multiply);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	multiplicand_ovl.full = multiplicand;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	/*
59*4882a593Smuzhiyun 	 * The Product is 64 bits, the carry is always 32 bits,
60*4882a593Smuzhiyun 	 * and is generated by the second multiply.
61*4882a593Smuzhiyun 	 */
62*4882a593Smuzhiyun 	ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.hi, multiplier,
63*4882a593Smuzhiyun 			  product.part.hi, carry32);
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.lo, multiplier,
66*4882a593Smuzhiyun 			  product.part.lo, carry32);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	product.part.hi += carry32;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/* Return only what was requested */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	if (out_product) {
73*4882a593Smuzhiyun 		*out_product = product.full;
74*4882a593Smuzhiyun 	}
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /*******************************************************************************
80*4882a593Smuzhiyun  *
81*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_shift_left
82*4882a593Smuzhiyun  *
83*4882a593Smuzhiyun  * PARAMETERS:  operand             - 64-bit shift operand
84*4882a593Smuzhiyun  *              count               - 32-bit shift count
85*4882a593Smuzhiyun  *              out_result          - Pointer to where the result is returned
86*4882a593Smuzhiyun  *
87*4882a593Smuzhiyun  * DESCRIPTION: Perform a short left shift.
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  ******************************************************************************/
90*4882a593Smuzhiyun 
acpi_ut_short_shift_left(u64 operand,u32 count,u64 * out_result)91*4882a593Smuzhiyun acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	union uint64_overlay operand_ovl;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_shift_left);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	operand_ovl.full = operand;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	if ((count & 63) >= 32) {
100*4882a593Smuzhiyun 		operand_ovl.part.hi = operand_ovl.part.lo;
101*4882a593Smuzhiyun 		operand_ovl.part.lo = 0;
102*4882a593Smuzhiyun 		count = (count & 63) - 32;
103*4882a593Smuzhiyun 	}
104*4882a593Smuzhiyun 	ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi,
105*4882a593Smuzhiyun 				 operand_ovl.part.lo, count);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	/* Return only what was requested */
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (out_result) {
110*4882a593Smuzhiyun 		*out_result = operand_ovl.full;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /*******************************************************************************
117*4882a593Smuzhiyun  *
118*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_shift_right
119*4882a593Smuzhiyun  *
120*4882a593Smuzhiyun  * PARAMETERS:  operand             - 64-bit shift operand
121*4882a593Smuzhiyun  *              count               - 32-bit shift count
122*4882a593Smuzhiyun  *              out_result          - Pointer to where the result is returned
123*4882a593Smuzhiyun  *
124*4882a593Smuzhiyun  * DESCRIPTION: Perform a short right shift.
125*4882a593Smuzhiyun  *
126*4882a593Smuzhiyun  ******************************************************************************/
127*4882a593Smuzhiyun 
acpi_ut_short_shift_right(u64 operand,u32 count,u64 * out_result)128*4882a593Smuzhiyun acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	union uint64_overlay operand_ovl;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_shift_right);
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	operand_ovl.full = operand;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if ((count & 63) >= 32) {
137*4882a593Smuzhiyun 		operand_ovl.part.lo = operand_ovl.part.hi;
138*4882a593Smuzhiyun 		operand_ovl.part.hi = 0;
139*4882a593Smuzhiyun 		count = (count & 63) - 32;
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun 	ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi,
142*4882a593Smuzhiyun 				  operand_ovl.part.lo, count);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/* Return only what was requested */
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (out_result) {
147*4882a593Smuzhiyun 		*out_result = operand_ovl.full;
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun #else
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun /*******************************************************************************
155*4882a593Smuzhiyun  *
156*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_multiply
157*4882a593Smuzhiyun  *
158*4882a593Smuzhiyun  * PARAMETERS:  See function headers above
159*4882a593Smuzhiyun  *
160*4882a593Smuzhiyun  * DESCRIPTION: Native version of the ut_short_multiply function.
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  ******************************************************************************/
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun acpi_status
acpi_ut_short_multiply(u64 multiplicand,u32 multiplier,u64 * out_product)165*4882a593Smuzhiyun acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_multiply);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* Return only what was requested */
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (out_product) {
173*4882a593Smuzhiyun 		*out_product = multiplicand * multiplier;
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun /*******************************************************************************
180*4882a593Smuzhiyun  *
181*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_shift_left
182*4882a593Smuzhiyun  *
183*4882a593Smuzhiyun  * PARAMETERS:  See function headers above
184*4882a593Smuzhiyun  *
185*4882a593Smuzhiyun  * DESCRIPTION: Native version of the ut_short_shift_left function.
186*4882a593Smuzhiyun  *
187*4882a593Smuzhiyun  ******************************************************************************/
188*4882a593Smuzhiyun 
acpi_ut_short_shift_left(u64 operand,u32 count,u64 * out_result)189*4882a593Smuzhiyun acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_shift_left);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* Return only what was requested */
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (out_result) {
197*4882a593Smuzhiyun 		*out_result = operand << count;
198*4882a593Smuzhiyun 	}
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun /*******************************************************************************
204*4882a593Smuzhiyun  *
205*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_shift_right
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  * PARAMETERS:  See function headers above
208*4882a593Smuzhiyun  *
209*4882a593Smuzhiyun  * DESCRIPTION: Native version of the ut_short_shift_right function.
210*4882a593Smuzhiyun  *
211*4882a593Smuzhiyun  ******************************************************************************/
212*4882a593Smuzhiyun 
acpi_ut_short_shift_right(u64 operand,u32 count,u64 * out_result)213*4882a593Smuzhiyun acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_shift_right);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* Return only what was requested */
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	if (out_result) {
221*4882a593Smuzhiyun 		*out_result = operand >> count;
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun #endif
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun /*
229*4882a593Smuzhiyun  * Optional support for 64-bit double-precision integer divide. This code
230*4882a593Smuzhiyun  * is configurable and is implemented in order to support 32-bit kernel
231*4882a593Smuzhiyun  * environments where a 64-bit double-precision math library is not available.
232*4882a593Smuzhiyun  *
233*4882a593Smuzhiyun  * Support for a more normal 64-bit divide/modulo (with check for a divide-
234*4882a593Smuzhiyun  * by-zero) appears after this optional section of code.
235*4882a593Smuzhiyun  */
236*4882a593Smuzhiyun #ifndef ACPI_USE_NATIVE_DIVIDE
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun /*******************************************************************************
239*4882a593Smuzhiyun  *
240*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_divide
241*4882a593Smuzhiyun  *
242*4882a593Smuzhiyun  * PARAMETERS:  dividend            - 64-bit dividend
243*4882a593Smuzhiyun  *              divisor             - 32-bit divisor
244*4882a593Smuzhiyun  *              out_quotient        - Pointer to where the quotient is returned
245*4882a593Smuzhiyun  *              out_remainder       - Pointer to where the remainder is returned
246*4882a593Smuzhiyun  *
247*4882a593Smuzhiyun  * RETURN:      Status (Checks for divide-by-zero)
248*4882a593Smuzhiyun  *
249*4882a593Smuzhiyun  * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
250*4882a593Smuzhiyun  *              divide and modulo. The result is a 64-bit quotient and a
251*4882a593Smuzhiyun  *              32-bit remainder.
252*4882a593Smuzhiyun  *
253*4882a593Smuzhiyun  ******************************************************************************/
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun acpi_status
acpi_ut_short_divide(u64 dividend,u32 divisor,u64 * out_quotient,u32 * out_remainder)256*4882a593Smuzhiyun acpi_ut_short_divide(u64 dividend,
257*4882a593Smuzhiyun 		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	union uint64_overlay dividend_ovl;
260*4882a593Smuzhiyun 	union uint64_overlay quotient;
261*4882a593Smuzhiyun 	u32 remainder32;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_divide);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	/* Always check for a zero divisor */
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	if (divisor == 0) {
268*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO, "Divide by zero"));
269*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	dividend_ovl.full = dividend;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	/*
275*4882a593Smuzhiyun 	 * The quotient is 64 bits, the remainder is always 32 bits,
276*4882a593Smuzhiyun 	 * and is generated by the second divide.
277*4882a593Smuzhiyun 	 */
278*4882a593Smuzhiyun 	ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
279*4882a593Smuzhiyun 			  quotient.part.hi, remainder32);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
282*4882a593Smuzhiyun 			  quotient.part.lo, remainder32);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	/* Return only what was requested */
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if (out_quotient) {
287*4882a593Smuzhiyun 		*out_quotient = quotient.full;
288*4882a593Smuzhiyun 	}
289*4882a593Smuzhiyun 	if (out_remainder) {
290*4882a593Smuzhiyun 		*out_remainder = remainder32;
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun /*******************************************************************************
297*4882a593Smuzhiyun  *
298*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_divide
299*4882a593Smuzhiyun  *
300*4882a593Smuzhiyun  * PARAMETERS:  in_dividend         - Dividend
301*4882a593Smuzhiyun  *              in_divisor          - Divisor
302*4882a593Smuzhiyun  *              out_quotient        - Pointer to where the quotient is returned
303*4882a593Smuzhiyun  *              out_remainder       - Pointer to where the remainder is returned
304*4882a593Smuzhiyun  *
305*4882a593Smuzhiyun  * RETURN:      Status (Checks for divide-by-zero)
306*4882a593Smuzhiyun  *
307*4882a593Smuzhiyun  * DESCRIPTION: Perform a divide and modulo.
308*4882a593Smuzhiyun  *
309*4882a593Smuzhiyun  ******************************************************************************/
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun acpi_status
acpi_ut_divide(u64 in_dividend,u64 in_divisor,u64 * out_quotient,u64 * out_remainder)312*4882a593Smuzhiyun acpi_ut_divide(u64 in_dividend,
313*4882a593Smuzhiyun 	       u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	union uint64_overlay dividend;
316*4882a593Smuzhiyun 	union uint64_overlay divisor;
317*4882a593Smuzhiyun 	union uint64_overlay quotient;
318*4882a593Smuzhiyun 	union uint64_overlay remainder;
319*4882a593Smuzhiyun 	union uint64_overlay normalized_dividend;
320*4882a593Smuzhiyun 	union uint64_overlay normalized_divisor;
321*4882a593Smuzhiyun 	u32 partial1;
322*4882a593Smuzhiyun 	union uint64_overlay partial2;
323*4882a593Smuzhiyun 	union uint64_overlay partial3;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_divide);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	/* Always check for a zero divisor */
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	if (in_divisor == 0) {
330*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO, "Divide by zero"));
331*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	divisor.full = in_divisor;
335*4882a593Smuzhiyun 	dividend.full = in_dividend;
336*4882a593Smuzhiyun 	if (divisor.part.hi == 0) {
337*4882a593Smuzhiyun 		/*
338*4882a593Smuzhiyun 		 * 1) Simplest case is where the divisor is 32 bits, we can
339*4882a593Smuzhiyun 		 * just do two divides
340*4882a593Smuzhiyun 		 */
341*4882a593Smuzhiyun 		remainder.part.hi = 0;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 		/*
344*4882a593Smuzhiyun 		 * The quotient is 64 bits, the remainder is always 32 bits,
345*4882a593Smuzhiyun 		 * and is generated by the second divide.
346*4882a593Smuzhiyun 		 */
347*4882a593Smuzhiyun 		ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
348*4882a593Smuzhiyun 				  quotient.part.hi, partial1);
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 		ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
351*4882a593Smuzhiyun 				  quotient.part.lo, remainder.part.lo);
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	else {
355*4882a593Smuzhiyun 		/*
356*4882a593Smuzhiyun 		 * 2) The general case where the divisor is a full 64 bits
357*4882a593Smuzhiyun 		 * is more difficult
358*4882a593Smuzhiyun 		 */
359*4882a593Smuzhiyun 		quotient.part.hi = 0;
360*4882a593Smuzhiyun 		normalized_dividend = dividend;
361*4882a593Smuzhiyun 		normalized_divisor = divisor;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 		/* Normalize the operands (shift until the divisor is < 32 bits) */
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 		do {
366*4882a593Smuzhiyun 			ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
367*4882a593Smuzhiyun 					    normalized_divisor.part.lo);
368*4882a593Smuzhiyun 			ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
369*4882a593Smuzhiyun 					    normalized_dividend.part.lo);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 		} while (normalized_divisor.part.hi != 0);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 		/* Partial divide */
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 		ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
376*4882a593Smuzhiyun 				  normalized_dividend.part.lo,
377*4882a593Smuzhiyun 				  normalized_divisor.part.lo, quotient.part.lo,
378*4882a593Smuzhiyun 				  partial1);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 		/*
381*4882a593Smuzhiyun 		 * The quotient is always 32 bits, and simply requires
382*4882a593Smuzhiyun 		 * adjustment. The 64-bit remainder must be generated.
383*4882a593Smuzhiyun 		 */
384*4882a593Smuzhiyun 		partial1 = quotient.part.lo * divisor.part.hi;
385*4882a593Smuzhiyun 		partial2.full = (u64) quotient.part.lo * divisor.part.lo;
386*4882a593Smuzhiyun 		partial3.full = (u64) partial2.part.hi + partial1;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		remainder.part.hi = partial3.part.lo;
389*4882a593Smuzhiyun 		remainder.part.lo = partial2.part.lo;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 		if (partial3.part.hi == 0) {
392*4882a593Smuzhiyun 			if (partial3.part.lo >= dividend.part.hi) {
393*4882a593Smuzhiyun 				if (partial3.part.lo == dividend.part.hi) {
394*4882a593Smuzhiyun 					if (partial2.part.lo > dividend.part.lo) {
395*4882a593Smuzhiyun 						quotient.part.lo--;
396*4882a593Smuzhiyun 						remainder.full -= divisor.full;
397*4882a593Smuzhiyun 					}
398*4882a593Smuzhiyun 				} else {
399*4882a593Smuzhiyun 					quotient.part.lo--;
400*4882a593Smuzhiyun 					remainder.full -= divisor.full;
401*4882a593Smuzhiyun 				}
402*4882a593Smuzhiyun 			}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 			remainder.full = remainder.full - dividend.full;
405*4882a593Smuzhiyun 			remainder.part.hi = (u32)-((s32)remainder.part.hi);
406*4882a593Smuzhiyun 			remainder.part.lo = (u32)-((s32)remainder.part.lo);
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 			if (remainder.part.lo) {
409*4882a593Smuzhiyun 				remainder.part.hi--;
410*4882a593Smuzhiyun 			}
411*4882a593Smuzhiyun 		}
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	/* Return only what was requested */
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	if (out_quotient) {
417*4882a593Smuzhiyun 		*out_quotient = quotient.full;
418*4882a593Smuzhiyun 	}
419*4882a593Smuzhiyun 	if (out_remainder) {
420*4882a593Smuzhiyun 		*out_remainder = remainder.full;
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun #else
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun /*******************************************************************************
429*4882a593Smuzhiyun  *
430*4882a593Smuzhiyun  * FUNCTION:    acpi_ut_short_divide, acpi_ut_divide
431*4882a593Smuzhiyun  *
432*4882a593Smuzhiyun  * PARAMETERS:  See function headers above
433*4882a593Smuzhiyun  *
434*4882a593Smuzhiyun  * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
435*4882a593Smuzhiyun  *              1) The target is a 64-bit platform and therefore 64-bit
436*4882a593Smuzhiyun  *                 integer math is supported directly by the machine.
437*4882a593Smuzhiyun  *              2) The target is a 32-bit or 16-bit platform, and the
438*4882a593Smuzhiyun  *                 double-precision integer math library is available to
439*4882a593Smuzhiyun  *                 perform the divide.
440*4882a593Smuzhiyun  *
441*4882a593Smuzhiyun  ******************************************************************************/
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun acpi_status
acpi_ut_short_divide(u64 in_dividend,u32 divisor,u64 * out_quotient,u32 * out_remainder)444*4882a593Smuzhiyun acpi_ut_short_divide(u64 in_dividend,
445*4882a593Smuzhiyun 		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_short_divide);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	/* Always check for a zero divisor */
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	if (divisor == 0) {
453*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO, "Divide by zero"));
454*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	/* Return only what was requested */
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	if (out_quotient) {
460*4882a593Smuzhiyun 		*out_quotient = in_dividend / divisor;
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 	if (out_remainder) {
463*4882a593Smuzhiyun 		*out_remainder = (u32) (in_dividend % divisor);
464*4882a593Smuzhiyun 	}
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun acpi_status
acpi_ut_divide(u64 in_dividend,u64 in_divisor,u64 * out_quotient,u64 * out_remainder)470*4882a593Smuzhiyun acpi_ut_divide(u64 in_dividend,
471*4882a593Smuzhiyun 	       u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ut_divide);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	/* Always check for a zero divisor */
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	if (in_divisor == 0) {
478*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO, "Divide by zero"));
479*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	/* Return only what was requested */
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	if (out_quotient) {
485*4882a593Smuzhiyun 		*out_quotient = in_dividend / in_divisor;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 	if (out_remainder) {
488*4882a593Smuzhiyun 		*out_remainder = in_dividend % in_divisor;
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun #endif
495