diff options
Diffstat (limited to 'sys/contrib/dev/acpica/exoparg1.c')
-rw-r--r-- | sys/contrib/dev/acpica/exoparg1.c | 85 |
1 files changed, 45 insertions, 40 deletions
diff --git a/sys/contrib/dev/acpica/exoparg1.c b/sys/contrib/dev/acpica/exoparg1.c index fae1ff8..46a149b 100644 --- a/sys/contrib/dev/acpica/exoparg1.c +++ b/sys/contrib/dev/acpica/exoparg1.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument - * $Revision: 147 $ + * $Revision: 148 $ * *****************************************************************************/ @@ -298,7 +298,7 @@ AcpiExOpcode_1A_1T_1R ( ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; UINT32 Temp32; UINT32 i; - UINT32 j; + UINT32 PowerOfTen; ACPI_INTEGER Digit; @@ -372,69 +372,74 @@ AcpiExOpcode_1A_1T_1R ( case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */ /* - * The 64-bit ACPI integer can hold 16 4-bit BCD integers + * The 64-bit ACPI integer can hold 16 4-bit BCD characters + * (if table is 32-bit, integer can hold 8 BCD characters) + * Convert each 4-bit BCD value */ + PowerOfTen = 1; ReturnDesc->Integer.Value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) + Digit = Operand[0]->Integer.Value; + + /* Convert each BCD digit (each is one nybble wide) */ + + for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) { - /* Get one BCD digit */ + /* Get the least significant 4-bit BCD digit */ - Digit = (ACPI_INTEGER) ((Operand[0]->Integer.Value >> (i * 4)) & 0xF); + Temp32 = ((UINT32) Digit) & 0xF; /* Check the range of the digit */ - if (Digit > 9) + if (Temp32 > 9) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: %d\n", - (UINT32) Digit)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "BCD digit too large (not decimal): 0x%X\n", + Temp32)); + Status = AE_AML_NUMERIC_OVERFLOW; goto Cleanup; } - if (Digit > 0) - { - /* Sum into the result with the appropriate power of 10 */ + /* Sum the digit into the result with the current power of 10 */ - for (j = 0; j < i; j++) - { - Digit *= 10; - } + ReturnDesc->Integer.Value += (((ACPI_INTEGER) Temp32) * PowerOfTen); - ReturnDesc->Integer.Value += Digit; - } + /* Shift to next BCD digit */ + + Digit >>= 4; + + /* Next power of 10 */ + + PowerOfTen *= 10; } break; case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */ - if (Operand[0]->Integer.Value > ACPI_MAX_BCD_VALUE) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %8.8X%8.8X\n", - ACPI_HIDWORD(Operand[0]->Integer.Value), - ACPI_LODWORD(Operand[0]->Integer.Value))); - Status = AE_AML_NUMERIC_OVERFLOW; - goto Cleanup; - } - ReturnDesc->Integer.Value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) + Digit = Operand[0]->Integer.Value; + + /* Each BCD digit is one nybble wide */ + + for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) { - /* Divide by nth factor of 10 */ + (void) AcpiUtShortDivide (&Digit, 10, &Digit, &Temp32); - Temp32 = 0; - Digit = Operand[0]->Integer.Value; - for (j = 0; j < i; j++) - { - (void) AcpiUtShortDivide (&Digit, 10, &Digit, &Temp32); - } + /* Insert the BCD digit that resides in the remainder from above */ - /* Create the BCD digit from the remainder above */ + ReturnDesc->Integer.Value |= (((ACPI_INTEGER) Temp32) << (i * 4)); + } - if (Digit > 0) - { - ReturnDesc->Integer.Value += ((ACPI_INTEGER) Temp32 << (i * 4)); - } + /* Overflow if there is any data left in Digit */ + + if (Digit > 0) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Integer too large to convert to BCD: %8.8X%8.8X\n", + ACPI_HIDWORD(Operand[0]->Integer.Value), + ACPI_LODWORD(Operand[0]->Integer.Value))); + Status = AE_AML_NUMERIC_OVERFLOW; + goto Cleanup; } break; |