xref: /openbmc/linux/drivers/acpi/acpica/utmath.c (revision 95857638)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: utmath - Integer math support routines
595b482a8SLen Brown  *
695b482a8SLen Brown  ******************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown #include <acpi/acpi.h>
9e2f7a777SLen Brown #include "accommon.h"
1095b482a8SLen Brown 
1195b482a8SLen Brown #define _COMPONENT          ACPI_UTILITIES
1295b482a8SLen Brown ACPI_MODULE_NAME("utmath")
1395b482a8SLen Brown 
14e786db75SBob Moore /* Structures used only for 64-bit divide */
15e786db75SBob Moore typedef struct uint64_struct {
16e786db75SBob Moore 	u32 lo;
17e786db75SBob Moore 	u32 hi;
18e786db75SBob Moore 
19e786db75SBob Moore } uint64_struct;
20e786db75SBob Moore 
21e786db75SBob Moore typedef union uint64_overlay {
22e786db75SBob Moore 	u64 full;
23e786db75SBob Moore 	struct uint64_struct part;
24e786db75SBob Moore 
25e786db75SBob Moore } uint64_overlay;
26e786db75SBob Moore 
2765082bfcSLv Zheng /*
2865082bfcSLv Zheng  * Optional support for 64-bit double-precision integer multiply and shift.
2965082bfcSLv Zheng  * This code is configurable and is implemented in order to support 32-bit
3065082bfcSLv Zheng  * kernel environments where a 64-bit double-precision math library is not
3165082bfcSLv Zheng  * available.
3265082bfcSLv Zheng  */
3365082bfcSLv Zheng #ifndef ACPI_USE_NATIVE_MATH64
3465082bfcSLv Zheng 
3565082bfcSLv Zheng /*******************************************************************************
3665082bfcSLv Zheng  *
3765082bfcSLv Zheng  * FUNCTION:    acpi_ut_short_multiply
3865082bfcSLv Zheng  *
3965082bfcSLv Zheng  * PARAMETERS:  multiplicand        - 64-bit multiplicand
4065082bfcSLv Zheng  *              multiplier          - 32-bit multiplier
4165082bfcSLv Zheng  *              out_product         - Pointer to where the product is returned
4265082bfcSLv Zheng  *
4365082bfcSLv Zheng  * DESCRIPTION: Perform a short multiply.
4465082bfcSLv Zheng  *
4565082bfcSLv Zheng  ******************************************************************************/
4665082bfcSLv Zheng 
4765082bfcSLv Zheng acpi_status
acpi_ut_short_multiply(u64 multiplicand,u32 multiplier,u64 * out_product)4865082bfcSLv Zheng acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
4965082bfcSLv Zheng {
5065082bfcSLv Zheng 	union uint64_overlay multiplicand_ovl;
5165082bfcSLv Zheng 	union uint64_overlay product;
5265082bfcSLv Zheng 	u32 carry32;
5365082bfcSLv Zheng 
5465082bfcSLv Zheng 	ACPI_FUNCTION_TRACE(ut_short_multiply);
5565082bfcSLv Zheng 
5665082bfcSLv Zheng 	multiplicand_ovl.full = multiplicand;
5765082bfcSLv Zheng 
5865082bfcSLv Zheng 	/*
5965082bfcSLv Zheng 	 * The Product is 64 bits, the carry is always 32 bits,
6065082bfcSLv Zheng 	 * and is generated by the second multiply.
6165082bfcSLv Zheng 	 */
6265082bfcSLv Zheng 	ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.hi, multiplier,
6365082bfcSLv Zheng 			  product.part.hi, carry32);
6465082bfcSLv Zheng 
6565082bfcSLv Zheng 	ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.lo, multiplier,
6665082bfcSLv Zheng 			  product.part.lo, carry32);
6765082bfcSLv Zheng 
6865082bfcSLv Zheng 	product.part.hi += carry32;
6965082bfcSLv Zheng 
7065082bfcSLv Zheng 	/* Return only what was requested */
7165082bfcSLv Zheng 
7265082bfcSLv Zheng 	if (out_product) {
7365082bfcSLv Zheng 		*out_product = product.full;
7465082bfcSLv Zheng 	}
7565082bfcSLv Zheng 
7665082bfcSLv Zheng 	return_ACPI_STATUS(AE_OK);
7765082bfcSLv Zheng }
7865082bfcSLv Zheng 
7965082bfcSLv Zheng /*******************************************************************************
8065082bfcSLv Zheng  *
8165082bfcSLv Zheng  * FUNCTION:    acpi_ut_short_shift_left
8265082bfcSLv Zheng  *
8365082bfcSLv Zheng  * PARAMETERS:  operand             - 64-bit shift operand
8465082bfcSLv Zheng  *              count               - 32-bit shift count
8565082bfcSLv Zheng  *              out_result          - Pointer to where the result is returned
8665082bfcSLv Zheng  *
8765082bfcSLv Zheng  * DESCRIPTION: Perform a short left shift.
8865082bfcSLv Zheng  *
8965082bfcSLv Zheng  ******************************************************************************/
9065082bfcSLv Zheng 
acpi_ut_short_shift_left(u64 operand,u32 count,u64 * out_result)9165082bfcSLv Zheng acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
9265082bfcSLv Zheng {
9365082bfcSLv Zheng 	union uint64_overlay operand_ovl;
9465082bfcSLv Zheng 
9565082bfcSLv Zheng 	ACPI_FUNCTION_TRACE(ut_short_shift_left);
9665082bfcSLv Zheng 
9765082bfcSLv Zheng 	operand_ovl.full = operand;
9865082bfcSLv Zheng 
9965082bfcSLv Zheng 	if ((count & 63) >= 32) {
10065082bfcSLv Zheng 		operand_ovl.part.hi = operand_ovl.part.lo;
10119654f9fSLv Zheng 		operand_ovl.part.lo = 0;
10265082bfcSLv Zheng 		count = (count & 63) - 32;
10365082bfcSLv Zheng 	}
10465082bfcSLv Zheng 	ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi,
10565082bfcSLv Zheng 				 operand_ovl.part.lo, count);
10665082bfcSLv Zheng 
10765082bfcSLv Zheng 	/* Return only what was requested */
10865082bfcSLv Zheng 
10965082bfcSLv Zheng 	if (out_result) {
11065082bfcSLv Zheng 		*out_result = operand_ovl.full;
11165082bfcSLv Zheng 	}
11265082bfcSLv Zheng 
11365082bfcSLv Zheng 	return_ACPI_STATUS(AE_OK);
11465082bfcSLv Zheng }
11565082bfcSLv Zheng 
11665082bfcSLv Zheng /*******************************************************************************
11765082bfcSLv Zheng  *
11865082bfcSLv Zheng  * FUNCTION:    acpi_ut_short_shift_right
11965082bfcSLv Zheng  *
12065082bfcSLv Zheng  * PARAMETERS:  operand             - 64-bit shift operand
12165082bfcSLv Zheng  *              count               - 32-bit shift count
12265082bfcSLv Zheng  *              out_result          - Pointer to where the result is returned
12365082bfcSLv Zheng  *
12465082bfcSLv Zheng  * DESCRIPTION: Perform a short right shift.
12565082bfcSLv Zheng  *
12665082bfcSLv Zheng  ******************************************************************************/
12765082bfcSLv Zheng 
acpi_ut_short_shift_right(u64 operand,u32 count,u64 * out_result)12865082bfcSLv Zheng acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
12965082bfcSLv Zheng {
13065082bfcSLv Zheng 	union uint64_overlay operand_ovl;
13165082bfcSLv Zheng 
13265082bfcSLv Zheng 	ACPI_FUNCTION_TRACE(ut_short_shift_right);
13365082bfcSLv Zheng 
13465082bfcSLv Zheng 	operand_ovl.full = operand;
13565082bfcSLv Zheng 
13665082bfcSLv Zheng 	if ((count & 63) >= 32) {
13765082bfcSLv Zheng 		operand_ovl.part.lo = operand_ovl.part.hi;
13819654f9fSLv Zheng 		operand_ovl.part.hi = 0;
13965082bfcSLv Zheng 		count = (count & 63) - 32;
14065082bfcSLv Zheng 	}
14165082bfcSLv Zheng 	ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi,
14265082bfcSLv Zheng 				  operand_ovl.part.lo, count);
14365082bfcSLv Zheng 
14465082bfcSLv Zheng 	/* Return only what was requested */
14565082bfcSLv Zheng 
14665082bfcSLv Zheng 	if (out_result) {
14765082bfcSLv Zheng 		*out_result = operand_ovl.full;
14865082bfcSLv Zheng 	}
14965082bfcSLv Zheng 
15065082bfcSLv Zheng 	return_ACPI_STATUS(AE_OK);
15165082bfcSLv Zheng }
15265082bfcSLv Zheng #else
15365082bfcSLv Zheng 
15465082bfcSLv Zheng /*******************************************************************************
15565082bfcSLv Zheng  *
15665082bfcSLv Zheng  * FUNCTION:    acpi_ut_short_multiply
15765082bfcSLv Zheng  *
15865082bfcSLv Zheng  * PARAMETERS:  See function headers above
15965082bfcSLv Zheng  *
16065082bfcSLv Zheng  * DESCRIPTION: Native version of the ut_short_multiply function.
16165082bfcSLv Zheng  *
16265082bfcSLv Zheng  ******************************************************************************/
16365082bfcSLv Zheng 
16465082bfcSLv Zheng acpi_status
acpi_ut_short_multiply(u64 multiplicand,u32 multiplier,u64 * out_product)16565082bfcSLv Zheng acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
16665082bfcSLv Zheng {
16765082bfcSLv Zheng 
16865082bfcSLv Zheng 	ACPI_FUNCTION_TRACE(ut_short_multiply);
16965082bfcSLv Zheng 
17065082bfcSLv Zheng 	/* Return only what was requested */
17165082bfcSLv Zheng 
17265082bfcSLv Zheng 	if (out_product) {
17365082bfcSLv Zheng 		*out_product = multiplicand * multiplier;
17465082bfcSLv Zheng 	}
17565082bfcSLv Zheng 
17665082bfcSLv Zheng 	return_ACPI_STATUS(AE_OK);
17765082bfcSLv Zheng }
17865082bfcSLv Zheng 
17965082bfcSLv Zheng /*******************************************************************************
18065082bfcSLv Zheng  *
18165082bfcSLv Zheng  * FUNCTION:    acpi_ut_short_shift_left
18265082bfcSLv Zheng  *
18365082bfcSLv Zheng  * PARAMETERS:  See function headers above
18465082bfcSLv Zheng  *
18565082bfcSLv Zheng  * DESCRIPTION: Native version of the ut_short_shift_left function.
18665082bfcSLv Zheng  *
18765082bfcSLv Zheng  ******************************************************************************/
18865082bfcSLv Zheng 
acpi_ut_short_shift_left(u64 operand,u32 count,u64 * out_result)18965082bfcSLv Zheng acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
19065082bfcSLv Zheng {
19165082bfcSLv Zheng 
19265082bfcSLv Zheng 	ACPI_FUNCTION_TRACE(ut_short_shift_left);
19365082bfcSLv Zheng 
19465082bfcSLv Zheng 	/* Return only what was requested */
19565082bfcSLv Zheng 
19665082bfcSLv Zheng 	if (out_result) {
19765082bfcSLv Zheng 		*out_result = operand << count;
19865082bfcSLv Zheng 	}
19965082bfcSLv Zheng 
20065082bfcSLv Zheng 	return_ACPI_STATUS(AE_OK);
20165082bfcSLv Zheng }
20265082bfcSLv Zheng 
20365082bfcSLv Zheng /*******************************************************************************
20465082bfcSLv Zheng  *
20565082bfcSLv Zheng  * FUNCTION:    acpi_ut_short_shift_right
20665082bfcSLv Zheng  *
20765082bfcSLv Zheng  * PARAMETERS:  See function headers above
20865082bfcSLv Zheng  *
20965082bfcSLv Zheng  * DESCRIPTION: Native version of the ut_short_shift_right function.
21065082bfcSLv Zheng  *
21165082bfcSLv Zheng  ******************************************************************************/
21265082bfcSLv Zheng 
acpi_ut_short_shift_right(u64 operand,u32 count,u64 * out_result)21365082bfcSLv Zheng acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
21465082bfcSLv Zheng {
21565082bfcSLv Zheng 
21665082bfcSLv Zheng 	ACPI_FUNCTION_TRACE(ut_short_shift_right);
21765082bfcSLv Zheng 
21865082bfcSLv Zheng 	/* Return only what was requested */
21965082bfcSLv Zheng 
22065082bfcSLv Zheng 	if (out_result) {
22165082bfcSLv Zheng 		*out_result = operand >> count;
22265082bfcSLv Zheng 	}
22365082bfcSLv Zheng 
22465082bfcSLv Zheng 	return_ACPI_STATUS(AE_OK);
22565082bfcSLv Zheng }
22665082bfcSLv Zheng #endif
22765082bfcSLv Zheng 
22865082bfcSLv Zheng /*
22965082bfcSLv Zheng  * Optional support for 64-bit double-precision integer divide. This code
23065082bfcSLv Zheng  * is configurable and is implemented in order to support 32-bit kernel
23165082bfcSLv Zheng  * environments where a 64-bit double-precision math library is not available.
23265082bfcSLv Zheng  *
23365082bfcSLv Zheng  * Support for a more normal 64-bit divide/modulo (with check for a divide-
23465082bfcSLv Zheng  * by-zero) appears after this optional section of code.
23565082bfcSLv Zheng  */
23665082bfcSLv Zheng #ifndef ACPI_USE_NATIVE_DIVIDE
23765082bfcSLv Zheng 
23895b482a8SLen Brown /*******************************************************************************
23995b482a8SLen Brown  *
24095b482a8SLen Brown  * FUNCTION:    acpi_ut_short_divide
24195b482a8SLen Brown  *
242ba494beeSBob Moore  * PARAMETERS:  dividend            - 64-bit dividend
243ba494beeSBob Moore  *              divisor             - 32-bit divisor
24495b482a8SLen Brown  *              out_quotient        - Pointer to where the quotient is returned
24595b482a8SLen Brown  *              out_remainder       - Pointer to where the remainder is returned
24695b482a8SLen Brown  *
24795b482a8SLen Brown  * RETURN:      Status (Checks for divide-by-zero)
24895b482a8SLen Brown  *
24995b482a8SLen Brown  * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
25095b482a8SLen Brown  *              divide and modulo. The result is a 64-bit quotient and a
25195b482a8SLen Brown  *              32-bit remainder.
25295b482a8SLen Brown  *
25395b482a8SLen Brown  ******************************************************************************/
254e786db75SBob Moore 
25595b482a8SLen Brown acpi_status
acpi_ut_short_divide(u64 dividend,u32 divisor,u64 * out_quotient,u32 * out_remainder)2565df7e6cbSBob Moore acpi_ut_short_divide(u64 dividend,
2575df7e6cbSBob Moore 		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
25895b482a8SLen Brown {
25995b482a8SLen Brown 	union uint64_overlay dividend_ovl;
26095b482a8SLen Brown 	union uint64_overlay quotient;
26195b482a8SLen Brown 	u32 remainder32;
26295b482a8SLen Brown 
26395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_short_divide);
26495b482a8SLen Brown 
26595b482a8SLen Brown 	/* Always check for a zero divisor */
26695b482a8SLen Brown 
26795b482a8SLen Brown 	if (divisor == 0) {
26895b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Divide by zero"));
26995b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
27095b482a8SLen Brown 	}
27195b482a8SLen Brown 
27295b482a8SLen Brown 	dividend_ovl.full = dividend;
27395b482a8SLen Brown 
27495b482a8SLen Brown 	/*
27595b482a8SLen Brown 	 * The quotient is 64 bits, the remainder is always 32 bits,
27695b482a8SLen Brown 	 * and is generated by the second divide.
27795b482a8SLen Brown 	 */
27895b482a8SLen Brown 	ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
27995b482a8SLen Brown 			  quotient.part.hi, remainder32);
2801fad8738SBob Moore 
28195b482a8SLen Brown 	ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
28295b482a8SLen Brown 			  quotient.part.lo, remainder32);
28395b482a8SLen Brown 
28495b482a8SLen Brown 	/* Return only what was requested */
28595b482a8SLen Brown 
28695b482a8SLen Brown 	if (out_quotient) {
28795b482a8SLen Brown 		*out_quotient = quotient.full;
28895b482a8SLen Brown 	}
28995b482a8SLen Brown 	if (out_remainder) {
29095b482a8SLen Brown 		*out_remainder = remainder32;
29195b482a8SLen Brown 	}
29295b482a8SLen Brown 
29395b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
29495b482a8SLen Brown }
29595b482a8SLen Brown 
29695b482a8SLen Brown /*******************************************************************************
29795b482a8SLen Brown  *
29895b482a8SLen Brown  * FUNCTION:    acpi_ut_divide
29995b482a8SLen Brown  *
30095b482a8SLen Brown  * PARAMETERS:  in_dividend         - Dividend
30195b482a8SLen Brown  *              in_divisor          - Divisor
30295b482a8SLen Brown  *              out_quotient        - Pointer to where the quotient is returned
30395b482a8SLen Brown  *              out_remainder       - Pointer to where the remainder is returned
30495b482a8SLen Brown  *
30595b482a8SLen Brown  * RETURN:      Status (Checks for divide-by-zero)
30695b482a8SLen Brown  *
30795b482a8SLen Brown  * DESCRIPTION: Perform a divide and modulo.
30895b482a8SLen Brown  *
30995b482a8SLen Brown  ******************************************************************************/
31095b482a8SLen Brown 
31195b482a8SLen Brown acpi_status
acpi_ut_divide(u64 in_dividend,u64 in_divisor,u64 * out_quotient,u64 * out_remainder)3125df7e6cbSBob Moore acpi_ut_divide(u64 in_dividend,
3135df7e6cbSBob Moore 	       u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
31495b482a8SLen Brown {
31595b482a8SLen Brown 	union uint64_overlay dividend;
31695b482a8SLen Brown 	union uint64_overlay divisor;
31795b482a8SLen Brown 	union uint64_overlay quotient;
31895b482a8SLen Brown 	union uint64_overlay remainder;
31995b482a8SLen Brown 	union uint64_overlay normalized_dividend;
32095b482a8SLen Brown 	union uint64_overlay normalized_divisor;
32195b482a8SLen Brown 	u32 partial1;
32295b482a8SLen Brown 	union uint64_overlay partial2;
32395b482a8SLen Brown 	union uint64_overlay partial3;
32495b482a8SLen Brown 
32595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_divide);
32695b482a8SLen Brown 
32795b482a8SLen Brown 	/* Always check for a zero divisor */
32895b482a8SLen Brown 
32995b482a8SLen Brown 	if (in_divisor == 0) {
33095b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Divide by zero"));
33195b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
33295b482a8SLen Brown 	}
33395b482a8SLen Brown 
33495b482a8SLen Brown 	divisor.full = in_divisor;
33595b482a8SLen Brown 	dividend.full = in_dividend;
33695b482a8SLen Brown 	if (divisor.part.hi == 0) {
33795b482a8SLen Brown 		/*
33895b482a8SLen Brown 		 * 1) Simplest case is where the divisor is 32 bits, we can
33995b482a8SLen Brown 		 * just do two divides
34095b482a8SLen Brown 		 */
34195b482a8SLen Brown 		remainder.part.hi = 0;
34295b482a8SLen Brown 
34395b482a8SLen Brown 		/*
34495b482a8SLen Brown 		 * The quotient is 64 bits, the remainder is always 32 bits,
34595b482a8SLen Brown 		 * and is generated by the second divide.
34695b482a8SLen Brown 		 */
34795b482a8SLen Brown 		ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
34895b482a8SLen Brown 				  quotient.part.hi, partial1);
3491fad8738SBob Moore 
35095b482a8SLen Brown 		ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
35195b482a8SLen Brown 				  quotient.part.lo, remainder.part.lo);
35295b482a8SLen Brown 	}
35395b482a8SLen Brown 
35495b482a8SLen Brown 	else {
35595b482a8SLen Brown 		/*
35695b482a8SLen Brown 		 * 2) The general case where the divisor is a full 64 bits
35795b482a8SLen Brown 		 * is more difficult
35895b482a8SLen Brown 		 */
35995b482a8SLen Brown 		quotient.part.hi = 0;
36095b482a8SLen Brown 		normalized_dividend = dividend;
36195b482a8SLen Brown 		normalized_divisor = divisor;
36295b482a8SLen Brown 
36395b482a8SLen Brown 		/* Normalize the operands (shift until the divisor is < 32 bits) */
36495b482a8SLen Brown 
36595b482a8SLen Brown 		do {
36695b482a8SLen Brown 			ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
36795b482a8SLen Brown 					    normalized_divisor.part.lo);
36895b482a8SLen Brown 			ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
36995b482a8SLen Brown 					    normalized_dividend.part.lo);
37095b482a8SLen Brown 
37195b482a8SLen Brown 		} while (normalized_divisor.part.hi != 0);
37295b482a8SLen Brown 
37395b482a8SLen Brown 		/* Partial divide */
37495b482a8SLen Brown 
37595b482a8SLen Brown 		ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
37695b482a8SLen Brown 				  normalized_dividend.part.lo,
3771fad8738SBob Moore 				  normalized_divisor.part.lo, quotient.part.lo,
3781fad8738SBob Moore 				  partial1);
37995b482a8SLen Brown 
38095b482a8SLen Brown 		/*
3811fad8738SBob Moore 		 * The quotient is always 32 bits, and simply requires
3821fad8738SBob Moore 		 * adjustment. The 64-bit remainder must be generated.
38395b482a8SLen Brown 		 */
38495b482a8SLen Brown 		partial1 = quotient.part.lo * divisor.part.hi;
3855df7e6cbSBob Moore 		partial2.full = (u64) quotient.part.lo * divisor.part.lo;
3865df7e6cbSBob Moore 		partial3.full = (u64) partial2.part.hi + partial1;
38795b482a8SLen Brown 
38895b482a8SLen Brown 		remainder.part.hi = partial3.part.lo;
38995b482a8SLen Brown 		remainder.part.lo = partial2.part.lo;
39095b482a8SLen Brown 
39195b482a8SLen Brown 		if (partial3.part.hi == 0) {
39295b482a8SLen Brown 			if (partial3.part.lo >= dividend.part.hi) {
39395b482a8SLen Brown 				if (partial3.part.lo == dividend.part.hi) {
39495b482a8SLen Brown 					if (partial2.part.lo > dividend.part.lo) {
39595b482a8SLen Brown 						quotient.part.lo--;
39695b482a8SLen Brown 						remainder.full -= divisor.full;
39795b482a8SLen Brown 					}
39895b482a8SLen Brown 				} else {
39995b482a8SLen Brown 					quotient.part.lo--;
40095b482a8SLen Brown 					remainder.full -= divisor.full;
40195b482a8SLen Brown 				}
40295b482a8SLen Brown 			}
40395b482a8SLen Brown 
40495b482a8SLen Brown 			remainder.full = remainder.full - dividend.full;
40595b482a8SLen Brown 			remainder.part.hi = (u32)-((s32)remainder.part.hi);
40695b482a8SLen Brown 			remainder.part.lo = (u32)-((s32)remainder.part.lo);
40795b482a8SLen Brown 
40895b482a8SLen Brown 			if (remainder.part.lo) {
40995b482a8SLen Brown 				remainder.part.hi--;
41095b482a8SLen Brown 			}
41195b482a8SLen Brown 		}
41295b482a8SLen Brown 	}
41395b482a8SLen Brown 
41495b482a8SLen Brown 	/* Return only what was requested */
41595b482a8SLen Brown 
41695b482a8SLen Brown 	if (out_quotient) {
41795b482a8SLen Brown 		*out_quotient = quotient.full;
41895b482a8SLen Brown 	}
41995b482a8SLen Brown 	if (out_remainder) {
42095b482a8SLen Brown 		*out_remainder = remainder.full;
42195b482a8SLen Brown 	}
42295b482a8SLen Brown 
42395b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
42495b482a8SLen Brown }
42595b482a8SLen Brown 
42695b482a8SLen Brown #else
42765082bfcSLv Zheng 
42895b482a8SLen Brown /*******************************************************************************
42995b482a8SLen Brown  *
43095b482a8SLen Brown  * FUNCTION:    acpi_ut_short_divide, acpi_ut_divide
43195b482a8SLen Brown  *
43295b482a8SLen Brown  * PARAMETERS:  See function headers above
43395b482a8SLen Brown  *
43495b482a8SLen Brown  * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
43595b482a8SLen Brown  *              1) The target is a 64-bit platform and therefore 64-bit
43695b482a8SLen Brown  *                 integer math is supported directly by the machine.
43795b482a8SLen Brown  *              2) The target is a 32-bit or 16-bit platform, and the
43895b482a8SLen Brown  *                 double-precision integer math library is available to
43995b482a8SLen Brown  *                 perform the divide.
44095b482a8SLen Brown  *
44195b482a8SLen Brown  ******************************************************************************/
44265082bfcSLv Zheng 
44395b482a8SLen Brown acpi_status
acpi_ut_short_divide(u64 in_dividend,u32 divisor,u64 * out_quotient,u32 * out_remainder)4445df7e6cbSBob Moore acpi_ut_short_divide(u64 in_dividend,
4455df7e6cbSBob Moore 		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
44695b482a8SLen Brown {
44795b482a8SLen Brown 
44895b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_short_divide);
44995b482a8SLen Brown 
45095b482a8SLen Brown 	/* Always check for a zero divisor */
45195b482a8SLen Brown 
45295b482a8SLen Brown 	if (divisor == 0) {
45395b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Divide by zero"));
45495b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
45595b482a8SLen Brown 	}
45695b482a8SLen Brown 
45795b482a8SLen Brown 	/* Return only what was requested */
45895b482a8SLen Brown 
45995b482a8SLen Brown 	if (out_quotient) {
46095b482a8SLen Brown 		*out_quotient = in_dividend / divisor;
46195b482a8SLen Brown 	}
46295b482a8SLen Brown 	if (out_remainder) {
46395b482a8SLen Brown 		*out_remainder = (u32) (in_dividend % divisor);
46495b482a8SLen Brown 	}
46595b482a8SLen Brown 
46695b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
46795b482a8SLen Brown }
46895b482a8SLen Brown 
46995b482a8SLen Brown acpi_status
acpi_ut_divide(u64 in_dividend,u64 in_divisor,u64 * out_quotient,u64 * out_remainder)4705df7e6cbSBob Moore acpi_ut_divide(u64 in_dividend,
4715df7e6cbSBob Moore 	       u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
47295b482a8SLen Brown {
47395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_divide);
47495b482a8SLen Brown 
47595b482a8SLen Brown 	/* Always check for a zero divisor */
47695b482a8SLen Brown 
47795b482a8SLen Brown 	if (in_divisor == 0) {
47895b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Divide by zero"));
47995b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
48095b482a8SLen Brown 	}
48195b482a8SLen Brown 
48295b482a8SLen Brown 	/* Return only what was requested */
48395b482a8SLen Brown 
48495b482a8SLen Brown 	if (out_quotient) {
48595b482a8SLen Brown 		*out_quotient = in_dividend / in_divisor;
48695b482a8SLen Brown 	}
48795b482a8SLen Brown 	if (out_remainder) {
48895b482a8SLen Brown 		*out_remainder = in_dividend % in_divisor;
48995b482a8SLen Brown 	}
49095b482a8SLen Brown 
49195b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
49295b482a8SLen Brown }
49395b482a8SLen Brown 
49495b482a8SLen Brown #endif
495