1
2
3
4
5
6
7
8#include <acpi/acpi.h>
9#include "accommon.h"
10
11#define _COMPONENT ACPI_UTILITIES
12ACPI_MODULE_NAME("utmath")
13
14
15typedef struct uint64_struct {
16 u32 lo;
17 u32 hi;
18
19} uint64_struct;
20
21typedef union uint64_overlay {
22 u64 full;
23 struct uint64_struct part;
24
25} uint64_overlay;
26
27
28
29
30
31
32
33#ifndef ACPI_USE_NATIVE_MATH64
34
35
36
37
38
39
40
41
42
43
44
45
46
47acpi_status
48acpi_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
60
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
71
72 if (out_product) {
73 *out_product = product.full;
74 }
75
76 return_ACPI_STATUS(AE_OK);
77}
78
79
80
81
82
83
84
85
86
87
88
89
90
91acpi_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
108
109 if (out_result) {
110 *out_result = operand_ovl.full;
111 }
112
113 return_ACPI_STATUS(AE_OK);
114}
115
116
117
118
119
120
121
122
123
124
125
126
127
128acpi_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
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
157
158
159
160
161
162
163
164acpi_status
165acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
166{
167
168 ACPI_FUNCTION_TRACE(ut_short_multiply);
169
170
171
172 if (out_product) {
173 *out_product = multiplicand * multiplier;
174 }
175
176 return_ACPI_STATUS(AE_OK);
177}
178
179
180
181
182
183
184
185
186
187
188
189acpi_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
195
196 if (out_result) {
197 *out_result = operand << count;
198 }
199
200 return_ACPI_STATUS(AE_OK);
201}
202
203
204
205
206
207
208
209
210
211
212
213acpi_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
219
220 if (out_result) {
221 *out_result = operand >> count;
222 }
223
224 return_ACPI_STATUS(AE_OK);
225}
226#endif
227
228
229
230
231
232
233
234
235
236#ifndef ACPI_USE_NATIVE_DIVIDE
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255acpi_status
256acpi_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
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
276
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
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
299
300
301
302
303
304
305
306
307
308
309
310
311acpi_status
312acpi_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
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
339
340
341 remainder.part.hi = 0;
342
343
344
345
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
357
358
359 quotient.part.hi = 0;
360 normalized_dividend = dividend;
361 normalized_divisor = divisor;
362
363
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
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
382
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
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
431
432
433
434
435
436
437
438
439
440
441
442
443acpi_status
444acpi_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
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
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
469acpi_status
470acpi_ut_divide(u64 in_dividend,
471 u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
472{
473 ACPI_FUNCTION_TRACE(ut_divide);
474
475
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
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
495