WIP FPC-III support
[linux/fpc-iii.git] / drivers / acpi / acpica / utmath.c
blob2c2c6bc1ff3f44999e9883bd550804faf3963515
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
4 * Module Name: utmath - Integer math support routines
6 ******************************************************************************/
8 #include <acpi/acpi.h>
9 #include "accommon.h"
11 #define _COMPONENT ACPI_UTILITIES
12 ACPI_MODULE_NAME("utmath")
14 /* Structures used only for 64-bit divide */
15 typedef struct uint64_struct {
16 u32 lo;
17 u32 hi;
19 } uint64_struct;
21 typedef union uint64_overlay {
22 u64 full;
23 struct uint64_struct part;
25 } uint64_overlay;
28 * Optional support for 64-bit double-precision integer multiply and shift.
29 * This code is configurable and is implemented in order to support 32-bit
30 * kernel environments where a 64-bit double-precision math library is not
31 * available.
33 #ifndef ACPI_USE_NATIVE_MATH64
35 /*******************************************************************************
37 * FUNCTION: acpi_ut_short_multiply
39 * PARAMETERS: multiplicand - 64-bit multiplicand
40 * multiplier - 32-bit multiplier
41 * out_product - Pointer to where the product is returned
43 * DESCRIPTION: Perform a short multiply.
45 ******************************************************************************/
47 acpi_status
48 acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
50 union uint64_overlay multiplicand_ovl;
51 union uint64_overlay product;
52 u32 carry32;
54 ACPI_FUNCTION_TRACE(ut_short_multiply);
56 multiplicand_ovl.full = multiplicand;
59 * The Product is 64 bits, the carry is always 32 bits,
60 * and is generated by the second multiply.
62 ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.hi, multiplier,
63 product.part.hi, carry32);
65 ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.lo, multiplier,
66 product.part.lo, carry32);
68 product.part.hi += carry32;
70 /* Return only what was requested */
72 if (out_product) {
73 *out_product = product.full;
76 return_ACPI_STATUS(AE_OK);
79 /*******************************************************************************
81 * FUNCTION: acpi_ut_short_shift_left
83 * PARAMETERS: operand - 64-bit shift operand
84 * count - 32-bit shift count
85 * out_result - Pointer to where the result is returned
87 * DESCRIPTION: Perform a short left shift.
89 ******************************************************************************/
91 acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
93 union uint64_overlay operand_ovl;
95 ACPI_FUNCTION_TRACE(ut_short_shift_left);
97 operand_ovl.full = operand;
99 if ((count & 63) >= 32) {
100 operand_ovl.part.hi = operand_ovl.part.lo;
101 operand_ovl.part.lo = 0;
102 count = (count & 63) - 32;
104 ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi,
105 operand_ovl.part.lo, count);
107 /* Return only what was requested */
109 if (out_result) {
110 *out_result = operand_ovl.full;
113 return_ACPI_STATUS(AE_OK);
116 /*******************************************************************************
118 * FUNCTION: acpi_ut_short_shift_right
120 * PARAMETERS: operand - 64-bit shift operand
121 * count - 32-bit shift count
122 * out_result - Pointer to where the result is returned
124 * DESCRIPTION: Perform a short right shift.
126 ******************************************************************************/
128 acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
130 union uint64_overlay operand_ovl;
132 ACPI_FUNCTION_TRACE(ut_short_shift_right);
134 operand_ovl.full = operand;
136 if ((count & 63) >= 32) {
137 operand_ovl.part.lo = operand_ovl.part.hi;
138 operand_ovl.part.hi = 0;
139 count = (count & 63) - 32;
141 ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi,
142 operand_ovl.part.lo, count);
144 /* Return only what was requested */
146 if (out_result) {
147 *out_result = operand_ovl.full;
150 return_ACPI_STATUS(AE_OK);
152 #else
154 /*******************************************************************************
156 * FUNCTION: acpi_ut_short_multiply
158 * PARAMETERS: See function headers above
160 * DESCRIPTION: Native version of the ut_short_multiply function.
162 ******************************************************************************/
164 acpi_status
165 acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
168 ACPI_FUNCTION_TRACE(ut_short_multiply);
170 /* Return only what was requested */
172 if (out_product) {
173 *out_product = multiplicand * multiplier;
176 return_ACPI_STATUS(AE_OK);
179 /*******************************************************************************
181 * FUNCTION: acpi_ut_short_shift_left
183 * PARAMETERS: See function headers above
185 * DESCRIPTION: Native version of the ut_short_shift_left function.
187 ******************************************************************************/
189 acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
192 ACPI_FUNCTION_TRACE(ut_short_shift_left);
194 /* Return only what was requested */
196 if (out_result) {
197 *out_result = operand << count;
200 return_ACPI_STATUS(AE_OK);
203 /*******************************************************************************
205 * FUNCTION: acpi_ut_short_shift_right
207 * PARAMETERS: See function headers above
209 * DESCRIPTION: Native version of the ut_short_shift_right function.
211 ******************************************************************************/
213 acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
216 ACPI_FUNCTION_TRACE(ut_short_shift_right);
218 /* Return only what was requested */
220 if (out_result) {
221 *out_result = operand >> count;
224 return_ACPI_STATUS(AE_OK);
226 #endif
229 * Optional support for 64-bit double-precision integer divide. This code
230 * is configurable and is implemented in order to support 32-bit kernel
231 * environments where a 64-bit double-precision math library is not available.
233 * Support for a more normal 64-bit divide/modulo (with check for a divide-
234 * by-zero) appears after this optional section of code.
236 #ifndef ACPI_USE_NATIVE_DIVIDE
238 /*******************************************************************************
240 * FUNCTION: acpi_ut_short_divide
242 * PARAMETERS: dividend - 64-bit dividend
243 * divisor - 32-bit divisor
244 * out_quotient - Pointer to where the quotient is returned
245 * out_remainder - Pointer to where the remainder is returned
247 * RETURN: Status (Checks for divide-by-zero)
249 * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
250 * divide and modulo. The result is a 64-bit quotient and a
251 * 32-bit remainder.
253 ******************************************************************************/
255 acpi_status
256 acpi_ut_short_divide(u64 dividend,
257 u32 divisor, u64 *out_quotient, u32 *out_remainder)
259 union uint64_overlay dividend_ovl;
260 union uint64_overlay quotient;
261 u32 remainder32;
263 ACPI_FUNCTION_TRACE(ut_short_divide);
265 /* Always check for a zero divisor */
267 if (divisor == 0) {
268 ACPI_ERROR((AE_INFO, "Divide by zero"));
269 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
272 dividend_ovl.full = dividend;
275 * The quotient is 64 bits, the remainder is always 32 bits,
276 * and is generated by the second divide.
278 ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
279 quotient.part.hi, remainder32);
281 ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
282 quotient.part.lo, remainder32);
284 /* Return only what was requested */
286 if (out_quotient) {
287 *out_quotient = quotient.full;
289 if (out_remainder) {
290 *out_remainder = remainder32;
293 return_ACPI_STATUS(AE_OK);
296 /*******************************************************************************
298 * FUNCTION: acpi_ut_divide
300 * PARAMETERS: in_dividend - Dividend
301 * in_divisor - Divisor
302 * out_quotient - Pointer to where the quotient is returned
303 * out_remainder - Pointer to where the remainder is returned
305 * RETURN: Status (Checks for divide-by-zero)
307 * DESCRIPTION: Perform a divide and modulo.
309 ******************************************************************************/
311 acpi_status
312 acpi_ut_divide(u64 in_dividend,
313 u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
315 union uint64_overlay dividend;
316 union uint64_overlay divisor;
317 union uint64_overlay quotient;
318 union uint64_overlay remainder;
319 union uint64_overlay normalized_dividend;
320 union uint64_overlay normalized_divisor;
321 u32 partial1;
322 union uint64_overlay partial2;
323 union uint64_overlay partial3;
325 ACPI_FUNCTION_TRACE(ut_divide);
327 /* Always check for a zero divisor */
329 if (in_divisor == 0) {
330 ACPI_ERROR((AE_INFO, "Divide by zero"));
331 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
334 divisor.full = in_divisor;
335 dividend.full = in_dividend;
336 if (divisor.part.hi == 0) {
338 * 1) Simplest case is where the divisor is 32 bits, we can
339 * just do two divides
341 remainder.part.hi = 0;
344 * The quotient is 64 bits, the remainder is always 32 bits,
345 * and is generated by the second divide.
347 ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
348 quotient.part.hi, partial1);
350 ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
351 quotient.part.lo, remainder.part.lo);
354 else {
356 * 2) The general case where the divisor is a full 64 bits
357 * is more difficult
359 quotient.part.hi = 0;
360 normalized_dividend = dividend;
361 normalized_divisor = divisor;
363 /* Normalize the operands (shift until the divisor is < 32 bits) */
365 do {
366 ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
367 normalized_divisor.part.lo);
368 ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
369 normalized_dividend.part.lo);
371 } while (normalized_divisor.part.hi != 0);
373 /* Partial divide */
375 ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
376 normalized_dividend.part.lo,
377 normalized_divisor.part.lo, quotient.part.lo,
378 partial1);
381 * The quotient is always 32 bits, and simply requires
382 * adjustment. The 64-bit remainder must be generated.
384 partial1 = quotient.part.lo * divisor.part.hi;
385 partial2.full = (u64) quotient.part.lo * divisor.part.lo;
386 partial3.full = (u64) partial2.part.hi + partial1;
388 remainder.part.hi = partial3.part.lo;
389 remainder.part.lo = partial2.part.lo;
391 if (partial3.part.hi == 0) {
392 if (partial3.part.lo >= dividend.part.hi) {
393 if (partial3.part.lo == dividend.part.hi) {
394 if (partial2.part.lo > dividend.part.lo) {
395 quotient.part.lo--;
396 remainder.full -= divisor.full;
398 } else {
399 quotient.part.lo--;
400 remainder.full -= divisor.full;
404 remainder.full = remainder.full - dividend.full;
405 remainder.part.hi = (u32)-((s32)remainder.part.hi);
406 remainder.part.lo = (u32)-((s32)remainder.part.lo);
408 if (remainder.part.lo) {
409 remainder.part.hi--;
414 /* Return only what was requested */
416 if (out_quotient) {
417 *out_quotient = quotient.full;
419 if (out_remainder) {
420 *out_remainder = remainder.full;
423 return_ACPI_STATUS(AE_OK);
426 #else
428 /*******************************************************************************
430 * FUNCTION: acpi_ut_short_divide, acpi_ut_divide
432 * PARAMETERS: See function headers above
434 * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
435 * 1) The target is a 64-bit platform and therefore 64-bit
436 * integer math is supported directly by the machine.
437 * 2) The target is a 32-bit or 16-bit platform, and the
438 * double-precision integer math library is available to
439 * perform the divide.
441 ******************************************************************************/
443 acpi_status
444 acpi_ut_short_divide(u64 in_dividend,
445 u32 divisor, u64 *out_quotient, u32 *out_remainder)
448 ACPI_FUNCTION_TRACE(ut_short_divide);
450 /* Always check for a zero divisor */
452 if (divisor == 0) {
453 ACPI_ERROR((AE_INFO, "Divide by zero"));
454 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
457 /* Return only what was requested */
459 if (out_quotient) {
460 *out_quotient = in_dividend / divisor;
462 if (out_remainder) {
463 *out_remainder = (u32) (in_dividend % divisor);
466 return_ACPI_STATUS(AE_OK);
469 acpi_status
470 acpi_ut_divide(u64 in_dividend,
471 u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
473 ACPI_FUNCTION_TRACE(ut_divide);
475 /* Always check for a zero divisor */
477 if (in_divisor == 0) {
478 ACPI_ERROR((AE_INFO, "Divide by zero"));
479 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
482 /* Return only what was requested */
484 if (out_quotient) {
485 *out_quotient = in_dividend / in_divisor;
487 if (out_remainder) {
488 *out_remainder = in_dividend % in_divisor;
491 return_ACPI_STATUS(AE_OK);
494 #endif