162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/*******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: utmath - Integer math support routines
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci ******************************************************************************/
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <acpi/acpi.h>
962306a36Sopenharmony_ci#include "accommon.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define _COMPONENT          ACPI_UTILITIES
1262306a36Sopenharmony_ciACPI_MODULE_NAME("utmath")
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/* Structures used only for 64-bit divide */
1562306a36Sopenharmony_citypedef struct uint64_struct {
1662306a36Sopenharmony_ci	u32 lo;
1762306a36Sopenharmony_ci	u32 hi;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci} uint64_struct;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_citypedef union uint64_overlay {
2262306a36Sopenharmony_ci	u64 full;
2362306a36Sopenharmony_ci	struct uint64_struct part;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci} uint64_overlay;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/*
2862306a36Sopenharmony_ci * Optional support for 64-bit double-precision integer multiply and shift.
2962306a36Sopenharmony_ci * This code is configurable and is implemented in order to support 32-bit
3062306a36Sopenharmony_ci * kernel environments where a 64-bit double-precision math library is not
3162306a36Sopenharmony_ci * available.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci#ifndef ACPI_USE_NATIVE_MATH64
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/*******************************************************************************
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_multiply
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci * PARAMETERS:  multiplicand        - 64-bit multiplicand
4062306a36Sopenharmony_ci *              multiplier          - 32-bit multiplier
4162306a36Sopenharmony_ci *              out_product         - Pointer to where the product is returned
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * DESCRIPTION: Perform a short multiply.
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci ******************************************************************************/
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciacpi_status
4862306a36Sopenharmony_ciacpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	union uint64_overlay multiplicand_ovl;
5162306a36Sopenharmony_ci	union uint64_overlay product;
5262306a36Sopenharmony_ci	u32 carry32;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_multiply);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	multiplicand_ovl.full = multiplicand;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	/*
5962306a36Sopenharmony_ci	 * The Product is 64 bits, the carry is always 32 bits,
6062306a36Sopenharmony_ci	 * and is generated by the second multiply.
6162306a36Sopenharmony_ci	 */
6262306a36Sopenharmony_ci	ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.hi, multiplier,
6362306a36Sopenharmony_ci			  product.part.hi, carry32);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.lo, multiplier,
6662306a36Sopenharmony_ci			  product.part.lo, carry32);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	product.part.hi += carry32;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* Return only what was requested */
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	if (out_product) {
7362306a36Sopenharmony_ci		*out_product = product.full;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/*******************************************************************************
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_shift_left
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci * PARAMETERS:  operand             - 64-bit shift operand
8462306a36Sopenharmony_ci *              count               - 32-bit shift count
8562306a36Sopenharmony_ci *              out_result          - Pointer to where the result is returned
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci * DESCRIPTION: Perform a short left shift.
8862306a36Sopenharmony_ci *
8962306a36Sopenharmony_ci ******************************************************************************/
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ciacpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	union uint64_overlay operand_ovl;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_shift_left);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	operand_ovl.full = operand;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	if ((count & 63) >= 32) {
10062306a36Sopenharmony_ci		operand_ovl.part.hi = operand_ovl.part.lo;
10162306a36Sopenharmony_ci		operand_ovl.part.lo = 0;
10262306a36Sopenharmony_ci		count = (count & 63) - 32;
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci	ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi,
10562306a36Sopenharmony_ci				 operand_ovl.part.lo, count);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* Return only what was requested */
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if (out_result) {
11062306a36Sopenharmony_ci		*out_result = operand_ovl.full;
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/*******************************************************************************
11762306a36Sopenharmony_ci *
11862306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_shift_right
11962306a36Sopenharmony_ci *
12062306a36Sopenharmony_ci * PARAMETERS:  operand             - 64-bit shift operand
12162306a36Sopenharmony_ci *              count               - 32-bit shift count
12262306a36Sopenharmony_ci *              out_result          - Pointer to where the result is returned
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci * DESCRIPTION: Perform a short right shift.
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci ******************************************************************************/
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciacpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	union uint64_overlay operand_ovl;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_shift_right);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	operand_ovl.full = operand;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	if ((count & 63) >= 32) {
13762306a36Sopenharmony_ci		operand_ovl.part.lo = operand_ovl.part.hi;
13862306a36Sopenharmony_ci		operand_ovl.part.hi = 0;
13962306a36Sopenharmony_ci		count = (count & 63) - 32;
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci	ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi,
14262306a36Sopenharmony_ci				  operand_ovl.part.lo, count);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* Return only what was requested */
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (out_result) {
14762306a36Sopenharmony_ci		*out_result = operand_ovl.full;
14862306a36Sopenharmony_ci	}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci#else
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci/*******************************************************************************
15562306a36Sopenharmony_ci *
15662306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_multiply
15762306a36Sopenharmony_ci *
15862306a36Sopenharmony_ci * PARAMETERS:  See function headers above
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * DESCRIPTION: Native version of the ut_short_multiply function.
16162306a36Sopenharmony_ci *
16262306a36Sopenharmony_ci ******************************************************************************/
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ciacpi_status
16562306a36Sopenharmony_ciacpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_multiply);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	/* Return only what was requested */
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	if (out_product) {
17362306a36Sopenharmony_ci		*out_product = multiplicand * multiplier;
17462306a36Sopenharmony_ci	}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/*******************************************************************************
18062306a36Sopenharmony_ci *
18162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_shift_left
18262306a36Sopenharmony_ci *
18362306a36Sopenharmony_ci * PARAMETERS:  See function headers above
18462306a36Sopenharmony_ci *
18562306a36Sopenharmony_ci * DESCRIPTION: Native version of the ut_short_shift_left function.
18662306a36Sopenharmony_ci *
18762306a36Sopenharmony_ci ******************************************************************************/
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ciacpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_shift_left);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	/* Return only what was requested */
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (out_result) {
19762306a36Sopenharmony_ci		*out_result = operand << count;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci/*******************************************************************************
20462306a36Sopenharmony_ci *
20562306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_shift_right
20662306a36Sopenharmony_ci *
20762306a36Sopenharmony_ci * PARAMETERS:  See function headers above
20862306a36Sopenharmony_ci *
20962306a36Sopenharmony_ci * DESCRIPTION: Native version of the ut_short_shift_right function.
21062306a36Sopenharmony_ci *
21162306a36Sopenharmony_ci ******************************************************************************/
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ciacpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_shift_right);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	/* Return only what was requested */
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (out_result) {
22162306a36Sopenharmony_ci		*out_result = operand >> count;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci#endif
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci/*
22962306a36Sopenharmony_ci * Optional support for 64-bit double-precision integer divide. This code
23062306a36Sopenharmony_ci * is configurable and is implemented in order to support 32-bit kernel
23162306a36Sopenharmony_ci * environments where a 64-bit double-precision math library is not available.
23262306a36Sopenharmony_ci *
23362306a36Sopenharmony_ci * Support for a more normal 64-bit divide/modulo (with check for a divide-
23462306a36Sopenharmony_ci * by-zero) appears after this optional section of code.
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_ci#ifndef ACPI_USE_NATIVE_DIVIDE
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/*******************************************************************************
23962306a36Sopenharmony_ci *
24062306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_divide
24162306a36Sopenharmony_ci *
24262306a36Sopenharmony_ci * PARAMETERS:  dividend            - 64-bit dividend
24362306a36Sopenharmony_ci *              divisor             - 32-bit divisor
24462306a36Sopenharmony_ci *              out_quotient        - Pointer to where the quotient is returned
24562306a36Sopenharmony_ci *              out_remainder       - Pointer to where the remainder is returned
24662306a36Sopenharmony_ci *
24762306a36Sopenharmony_ci * RETURN:      Status (Checks for divide-by-zero)
24862306a36Sopenharmony_ci *
24962306a36Sopenharmony_ci * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
25062306a36Sopenharmony_ci *              divide and modulo. The result is a 64-bit quotient and a
25162306a36Sopenharmony_ci *              32-bit remainder.
25262306a36Sopenharmony_ci *
25362306a36Sopenharmony_ci ******************************************************************************/
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ciacpi_status
25662306a36Sopenharmony_ciacpi_ut_short_divide(u64 dividend,
25762306a36Sopenharmony_ci		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	union uint64_overlay dividend_ovl;
26062306a36Sopenharmony_ci	union uint64_overlay quotient;
26162306a36Sopenharmony_ci	u32 remainder32;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_divide);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	/* Always check for a zero divisor */
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if (divisor == 0) {
26862306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "Divide by zero"));
26962306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	dividend_ovl.full = dividend;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	/*
27562306a36Sopenharmony_ci	 * The quotient is 64 bits, the remainder is always 32 bits,
27662306a36Sopenharmony_ci	 * and is generated by the second divide.
27762306a36Sopenharmony_ci	 */
27862306a36Sopenharmony_ci	ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
27962306a36Sopenharmony_ci			  quotient.part.hi, remainder32);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
28262306a36Sopenharmony_ci			  quotient.part.lo, remainder32);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Return only what was requested */
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if (out_quotient) {
28762306a36Sopenharmony_ci		*out_quotient = quotient.full;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci	if (out_remainder) {
29062306a36Sopenharmony_ci		*out_remainder = remainder32;
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci/*******************************************************************************
29762306a36Sopenharmony_ci *
29862306a36Sopenharmony_ci * FUNCTION:    acpi_ut_divide
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci * PARAMETERS:  in_dividend         - Dividend
30162306a36Sopenharmony_ci *              in_divisor          - Divisor
30262306a36Sopenharmony_ci *              out_quotient        - Pointer to where the quotient is returned
30362306a36Sopenharmony_ci *              out_remainder       - Pointer to where the remainder is returned
30462306a36Sopenharmony_ci *
30562306a36Sopenharmony_ci * RETURN:      Status (Checks for divide-by-zero)
30662306a36Sopenharmony_ci *
30762306a36Sopenharmony_ci * DESCRIPTION: Perform a divide and modulo.
30862306a36Sopenharmony_ci *
30962306a36Sopenharmony_ci ******************************************************************************/
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ciacpi_status
31262306a36Sopenharmony_ciacpi_ut_divide(u64 in_dividend,
31362306a36Sopenharmony_ci	       u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	union uint64_overlay dividend;
31662306a36Sopenharmony_ci	union uint64_overlay divisor;
31762306a36Sopenharmony_ci	union uint64_overlay quotient;
31862306a36Sopenharmony_ci	union uint64_overlay remainder;
31962306a36Sopenharmony_ci	union uint64_overlay normalized_dividend;
32062306a36Sopenharmony_ci	union uint64_overlay normalized_divisor;
32162306a36Sopenharmony_ci	u32 partial1;
32262306a36Sopenharmony_ci	union uint64_overlay partial2;
32362306a36Sopenharmony_ci	union uint64_overlay partial3;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_divide);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* Always check for a zero divisor */
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	if (in_divisor == 0) {
33062306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "Divide by zero"));
33162306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	divisor.full = in_divisor;
33562306a36Sopenharmony_ci	dividend.full = in_dividend;
33662306a36Sopenharmony_ci	if (divisor.part.hi == 0) {
33762306a36Sopenharmony_ci		/*
33862306a36Sopenharmony_ci		 * 1) Simplest case is where the divisor is 32 bits, we can
33962306a36Sopenharmony_ci		 * just do two divides
34062306a36Sopenharmony_ci		 */
34162306a36Sopenharmony_ci		remainder.part.hi = 0;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		/*
34462306a36Sopenharmony_ci		 * The quotient is 64 bits, the remainder is always 32 bits,
34562306a36Sopenharmony_ci		 * and is generated by the second divide.
34662306a36Sopenharmony_ci		 */
34762306a36Sopenharmony_ci		ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
34862306a36Sopenharmony_ci				  quotient.part.hi, partial1);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci		ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
35162306a36Sopenharmony_ci				  quotient.part.lo, remainder.part.lo);
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	else {
35562306a36Sopenharmony_ci		/*
35662306a36Sopenharmony_ci		 * 2) The general case where the divisor is a full 64 bits
35762306a36Sopenharmony_ci		 * is more difficult
35862306a36Sopenharmony_ci		 */
35962306a36Sopenharmony_ci		quotient.part.hi = 0;
36062306a36Sopenharmony_ci		normalized_dividend = dividend;
36162306a36Sopenharmony_ci		normalized_divisor = divisor;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci		/* Normalize the operands (shift until the divisor is < 32 bits) */
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci		do {
36662306a36Sopenharmony_ci			ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
36762306a36Sopenharmony_ci					    normalized_divisor.part.lo);
36862306a36Sopenharmony_ci			ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
36962306a36Sopenharmony_ci					    normalized_dividend.part.lo);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci		} while (normalized_divisor.part.hi != 0);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci		/* Partial divide */
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci		ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
37662306a36Sopenharmony_ci				  normalized_dividend.part.lo,
37762306a36Sopenharmony_ci				  normalized_divisor.part.lo, quotient.part.lo,
37862306a36Sopenharmony_ci				  partial1);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci		/*
38162306a36Sopenharmony_ci		 * The quotient is always 32 bits, and simply requires
38262306a36Sopenharmony_ci		 * adjustment. The 64-bit remainder must be generated.
38362306a36Sopenharmony_ci		 */
38462306a36Sopenharmony_ci		partial1 = quotient.part.lo * divisor.part.hi;
38562306a36Sopenharmony_ci		partial2.full = (u64) quotient.part.lo * divisor.part.lo;
38662306a36Sopenharmony_ci		partial3.full = (u64) partial2.part.hi + partial1;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci		remainder.part.hi = partial3.part.lo;
38962306a36Sopenharmony_ci		remainder.part.lo = partial2.part.lo;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		if (partial3.part.hi == 0) {
39262306a36Sopenharmony_ci			if (partial3.part.lo >= dividend.part.hi) {
39362306a36Sopenharmony_ci				if (partial3.part.lo == dividend.part.hi) {
39462306a36Sopenharmony_ci					if (partial2.part.lo > dividend.part.lo) {
39562306a36Sopenharmony_ci						quotient.part.lo--;
39662306a36Sopenharmony_ci						remainder.full -= divisor.full;
39762306a36Sopenharmony_ci					}
39862306a36Sopenharmony_ci				} else {
39962306a36Sopenharmony_ci					quotient.part.lo--;
40062306a36Sopenharmony_ci					remainder.full -= divisor.full;
40162306a36Sopenharmony_ci				}
40262306a36Sopenharmony_ci			}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci			remainder.full = remainder.full - dividend.full;
40562306a36Sopenharmony_ci			remainder.part.hi = (u32)-((s32)remainder.part.hi);
40662306a36Sopenharmony_ci			remainder.part.lo = (u32)-((s32)remainder.part.lo);
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci			if (remainder.part.lo) {
40962306a36Sopenharmony_ci				remainder.part.hi--;
41062306a36Sopenharmony_ci			}
41162306a36Sopenharmony_ci		}
41262306a36Sopenharmony_ci	}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	/* Return only what was requested */
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if (out_quotient) {
41762306a36Sopenharmony_ci		*out_quotient = quotient.full;
41862306a36Sopenharmony_ci	}
41962306a36Sopenharmony_ci	if (out_remainder) {
42062306a36Sopenharmony_ci		*out_remainder = remainder.full;
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci#else
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci/*******************************************************************************
42962306a36Sopenharmony_ci *
43062306a36Sopenharmony_ci * FUNCTION:    acpi_ut_short_divide, acpi_ut_divide
43162306a36Sopenharmony_ci *
43262306a36Sopenharmony_ci * PARAMETERS:  See function headers above
43362306a36Sopenharmony_ci *
43462306a36Sopenharmony_ci * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
43562306a36Sopenharmony_ci *              1) The target is a 64-bit platform and therefore 64-bit
43662306a36Sopenharmony_ci *                 integer math is supported directly by the machine.
43762306a36Sopenharmony_ci *              2) The target is a 32-bit or 16-bit platform, and the
43862306a36Sopenharmony_ci *                 double-precision integer math library is available to
43962306a36Sopenharmony_ci *                 perform the divide.
44062306a36Sopenharmony_ci *
44162306a36Sopenharmony_ci ******************************************************************************/
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ciacpi_status
44462306a36Sopenharmony_ciacpi_ut_short_divide(u64 in_dividend,
44562306a36Sopenharmony_ci		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_short_divide);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	/* Always check for a zero divisor */
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	if (divisor == 0) {
45362306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "Divide by zero"));
45462306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
45562306a36Sopenharmony_ci	}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	/* Return only what was requested */
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	if (out_quotient) {
46062306a36Sopenharmony_ci		*out_quotient = in_dividend / divisor;
46162306a36Sopenharmony_ci	}
46262306a36Sopenharmony_ci	if (out_remainder) {
46362306a36Sopenharmony_ci		*out_remainder = (u32) (in_dividend % divisor);
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ciacpi_status
47062306a36Sopenharmony_ciacpi_ut_divide(u64 in_dividend,
47162306a36Sopenharmony_ci	       u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_divide);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	/* Always check for a zero divisor */
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	if (in_divisor == 0) {
47862306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "Divide by zero"));
47962306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
48062306a36Sopenharmony_ci	}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	/* Return only what was requested */
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	if (out_quotient) {
48562306a36Sopenharmony_ci		*out_quotient = in_dividend / in_divisor;
48662306a36Sopenharmony_ci	}
48762306a36Sopenharmony_ci	if (out_remainder) {
48862306a36Sopenharmony_ci		*out_remainder = in_dividend % in_divisor;
48962306a36Sopenharmony_ci	}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci#endif
495