0001
0002
0003
0004
0005
0006
0007
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010
0011 #define _COMPONENT ACPI_UTILITIES
0012 ACPI_MODULE_NAME("utmath")
0013
0014
0015 typedef struct uint64_struct {
0016 u32 lo;
0017 u32 hi;
0018
0019 } uint64_struct;
0020
0021 typedef union uint64_overlay {
0022 u64 full;
0023 struct uint64_struct part;
0024
0025 } uint64_overlay;
0026
0027
0028
0029
0030
0031
0032
0033 #ifndef ACPI_USE_NATIVE_MATH64
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 acpi_status
0048 acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
0049 {
0050 union uint64_overlay multiplicand_ovl;
0051 union uint64_overlay product;
0052 u32 carry32;
0053
0054 ACPI_FUNCTION_TRACE(ut_short_multiply);
0055
0056 multiplicand_ovl.full = multiplicand;
0057
0058
0059
0060
0061
0062 ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.hi, multiplier,
0063 product.part.hi, carry32);
0064
0065 ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.lo, multiplier,
0066 product.part.lo, carry32);
0067
0068 product.part.hi += carry32;
0069
0070
0071
0072 if (out_product) {
0073 *out_product = product.full;
0074 }
0075
0076 return_ACPI_STATUS(AE_OK);
0077 }
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
0092 {
0093 union uint64_overlay operand_ovl;
0094
0095 ACPI_FUNCTION_TRACE(ut_short_shift_left);
0096
0097 operand_ovl.full = operand;
0098
0099 if ((count & 63) >= 32) {
0100 operand_ovl.part.hi = operand_ovl.part.lo;
0101 operand_ovl.part.lo = 0;
0102 count = (count & 63) - 32;
0103 }
0104 ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi,
0105 operand_ovl.part.lo, count);
0106
0107
0108
0109 if (out_result) {
0110 *out_result = operand_ovl.full;
0111 }
0112
0113 return_ACPI_STATUS(AE_OK);
0114 }
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
0129 {
0130 union uint64_overlay operand_ovl;
0131
0132 ACPI_FUNCTION_TRACE(ut_short_shift_right);
0133
0134 operand_ovl.full = operand;
0135
0136 if ((count & 63) >= 32) {
0137 operand_ovl.part.lo = operand_ovl.part.hi;
0138 operand_ovl.part.hi = 0;
0139 count = (count & 63) - 32;
0140 }
0141 ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi,
0142 operand_ovl.part.lo, count);
0143
0144
0145
0146 if (out_result) {
0147 *out_result = operand_ovl.full;
0148 }
0149
0150 return_ACPI_STATUS(AE_OK);
0151 }
0152 #else
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 acpi_status
0165 acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
0166 {
0167
0168 ACPI_FUNCTION_TRACE(ut_short_multiply);
0169
0170
0171
0172 if (out_product) {
0173 *out_product = multiplicand * multiplier;
0174 }
0175
0176 return_ACPI_STATUS(AE_OK);
0177 }
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
0190 {
0191
0192 ACPI_FUNCTION_TRACE(ut_short_shift_left);
0193
0194
0195
0196 if (out_result) {
0197 *out_result = operand << count;
0198 }
0199
0200 return_ACPI_STATUS(AE_OK);
0201 }
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
0214 {
0215
0216 ACPI_FUNCTION_TRACE(ut_short_shift_right);
0217
0218
0219
0220 if (out_result) {
0221 *out_result = operand >> count;
0222 }
0223
0224 return_ACPI_STATUS(AE_OK);
0225 }
0226 #endif
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 #ifndef ACPI_USE_NATIVE_DIVIDE
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 acpi_status
0256 acpi_ut_short_divide(u64 dividend,
0257 u32 divisor, u64 *out_quotient, u32 *out_remainder)
0258 {
0259 union uint64_overlay dividend_ovl;
0260 union uint64_overlay quotient;
0261 u32 remainder32;
0262
0263 ACPI_FUNCTION_TRACE(ut_short_divide);
0264
0265
0266
0267 if (divisor == 0) {
0268 ACPI_ERROR((AE_INFO, "Divide by zero"));
0269 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
0270 }
0271
0272 dividend_ovl.full = dividend;
0273
0274
0275
0276
0277
0278 ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
0279 quotient.part.hi, remainder32);
0280
0281 ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
0282 quotient.part.lo, remainder32);
0283
0284
0285
0286 if (out_quotient) {
0287 *out_quotient = quotient.full;
0288 }
0289 if (out_remainder) {
0290 *out_remainder = remainder32;
0291 }
0292
0293 return_ACPI_STATUS(AE_OK);
0294 }
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 acpi_status
0312 acpi_ut_divide(u64 in_dividend,
0313 u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
0314 {
0315 union uint64_overlay dividend;
0316 union uint64_overlay divisor;
0317 union uint64_overlay quotient;
0318 union uint64_overlay remainder;
0319 union uint64_overlay normalized_dividend;
0320 union uint64_overlay normalized_divisor;
0321 u32 partial1;
0322 union uint64_overlay partial2;
0323 union uint64_overlay partial3;
0324
0325 ACPI_FUNCTION_TRACE(ut_divide);
0326
0327
0328
0329 if (in_divisor == 0) {
0330 ACPI_ERROR((AE_INFO, "Divide by zero"));
0331 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
0332 }
0333
0334 divisor.full = in_divisor;
0335 dividend.full = in_dividend;
0336 if (divisor.part.hi == 0) {
0337
0338
0339
0340
0341 remainder.part.hi = 0;
0342
0343
0344
0345
0346
0347 ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
0348 quotient.part.hi, partial1);
0349
0350 ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
0351 quotient.part.lo, remainder.part.lo);
0352 }
0353
0354 else {
0355
0356
0357
0358
0359 quotient.part.hi = 0;
0360 normalized_dividend = dividend;
0361 normalized_divisor = divisor;
0362
0363
0364
0365 do {
0366 ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
0367 normalized_divisor.part.lo);
0368 ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
0369 normalized_dividend.part.lo);
0370
0371 } while (normalized_divisor.part.hi != 0);
0372
0373
0374
0375 ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
0376 normalized_dividend.part.lo,
0377 normalized_divisor.part.lo, quotient.part.lo,
0378 partial1);
0379
0380
0381
0382
0383
0384 partial1 = quotient.part.lo * divisor.part.hi;
0385 partial2.full = (u64) quotient.part.lo * divisor.part.lo;
0386 partial3.full = (u64) partial2.part.hi + partial1;
0387
0388 remainder.part.hi = partial3.part.lo;
0389 remainder.part.lo = partial2.part.lo;
0390
0391 if (partial3.part.hi == 0) {
0392 if (partial3.part.lo >= dividend.part.hi) {
0393 if (partial3.part.lo == dividend.part.hi) {
0394 if (partial2.part.lo > dividend.part.lo) {
0395 quotient.part.lo--;
0396 remainder.full -= divisor.full;
0397 }
0398 } else {
0399 quotient.part.lo--;
0400 remainder.full -= divisor.full;
0401 }
0402 }
0403
0404 remainder.full = remainder.full - dividend.full;
0405 remainder.part.hi = (u32)-((s32)remainder.part.hi);
0406 remainder.part.lo = (u32)-((s32)remainder.part.lo);
0407
0408 if (remainder.part.lo) {
0409 remainder.part.hi--;
0410 }
0411 }
0412 }
0413
0414
0415
0416 if (out_quotient) {
0417 *out_quotient = quotient.full;
0418 }
0419 if (out_remainder) {
0420 *out_remainder = remainder.full;
0421 }
0422
0423 return_ACPI_STATUS(AE_OK);
0424 }
0425
0426 #else
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 acpi_status
0444 acpi_ut_short_divide(u64 in_dividend,
0445 u32 divisor, u64 *out_quotient, u32 *out_remainder)
0446 {
0447
0448 ACPI_FUNCTION_TRACE(ut_short_divide);
0449
0450
0451
0452 if (divisor == 0) {
0453 ACPI_ERROR((AE_INFO, "Divide by zero"));
0454 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
0455 }
0456
0457
0458
0459 if (out_quotient) {
0460 *out_quotient = in_dividend / divisor;
0461 }
0462 if (out_remainder) {
0463 *out_remainder = (u32) (in_dividend % divisor);
0464 }
0465
0466 return_ACPI_STATUS(AE_OK);
0467 }
0468
0469 acpi_status
0470 acpi_ut_divide(u64 in_dividend,
0471 u64 in_divisor, u64 *out_quotient, u64 *out_remainder)
0472 {
0473 ACPI_FUNCTION_TRACE(ut_divide);
0474
0475
0476
0477 if (in_divisor == 0) {
0478 ACPI_ERROR((AE_INFO, "Divide by zero"));
0479 return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
0480 }
0481
0482
0483
0484 if (out_quotient) {
0485 *out_quotient = in_dividend / in_divisor;
0486 }
0487 if (out_remainder) {
0488 *out_remainder = in_dividend % in_divisor;
0489 }
0490
0491 return_ACPI_STATUS(AE_OK);
0492 }
0493
0494 #endif