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