src/add-ons/kernel/bus_managers/acpi/acpica/components/utilities/utmath.c
/*******************************************************************************
 *
 * FUNCTION:    AcpiUtDivide
 *
 * PARAMETERS:  InDividend          - Dividend
 *              InDivisor           - Divisor
 *              OutQuotient         - Pointer to where the quotient is returned
 *              OutRemainder        - Pointer to where the remainder is returned
 *
 * RETURN:      Status (Checks for divide-by-zero)
 *
 * DESCRIPTION: Perform a divide and modulo.
 *
 ******************************************************************************/
AcpiUtDivide
PARAMETERS:  InDividend          - Dividend
InDivisor           - Divisor
OutQuotient         - Pointer to where the quotient is returned
OutRemainder        - Pointer to where the remainder is returned

Status (Checks for divide-by-zero)

Perform a divide and modulo.
AcpiUtDivide PARAMETERS : InDividend - Dividend InDivisor - Divisor OutQuotient - Pointer to where the quotient is returned OutRemainder - Pointer to where the remainder is returned Status ( Checks for divide - by - zero ) Perform a divide and modulo .
ACPI_STATUS
AcpiUtDivide (
    UINT64                  InDividend,
    UINT64                  InDivisor,
    UINT64                  *OutQuotient,
    UINT64                  *OutRemainder)
{
    UINT64_OVERLAY          Dividend;
    UINT64_OVERLAY          Divisor;
    UINT64_OVERLAY          Quotient;
    UINT64_OVERLAY          Remainder;
    UINT64_OVERLAY          NormalizedDividend;
    UINT64_OVERLAY          NormalizedDivisor;
    UINT32                  Partial1;
    UINT64_OVERLAY          Partial2;
    UINT64_OVERLAY          Partial3;
    ACPI_FUNCTION_TRACE (UtDivide);
    if (InDivisor == 0)
    {
        ACPI_ERROR ((AE_INFO, "Divide by zero"));
        return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
    }
    Divisor.Full  = InDivisor;
    Dividend.Full = InDividend;
    if (Divisor.Part.Hi == 0)
    {
        Remainder.Part.Hi = 0;
        ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo,
            Quotient.Part.Hi, Partial1);
        ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo,
            Quotient.Part.Lo, Remainder.Part.Lo);
    }
    else
    {
        Quotient.Part.Hi   = 0;
        NormalizedDividend = Dividend;
        NormalizedDivisor  = Divisor;
        do
        {
            ACPI_SHIFT_RIGHT_64 (
                NormalizedDivisor.Part.Hi, NormalizedDivisor.Part.Lo);
            ACPI_SHIFT_RIGHT_64 (
                NormalizedDividend.Part.Hi, NormalizedDividend.Part.Lo);
        } while (NormalizedDivisor.Part.Hi != 0);
        ACPI_DIV_64_BY_32 (
            NormalizedDividend.Part.Hi, NormalizedDividend.Part.Lo,
            NormalizedDivisor.Part.Lo, Quotient.Part.Lo, Partial1);
        Partial1 = Quotient.Part.Lo * Divisor.Part.Hi;
        Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo;
        Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1;
        Remainder.Part.Hi = Partial3.Part.Lo;
        Remainder.Part.Lo = Partial2.Part.Lo;
        if (Partial3.Part.Hi == 0)
        {
            if (Partial3.Part.Lo >= Dividend.Part.Hi)
            {
                if (Partial3.Part.Lo == Dividend.Part.Hi)
                {
                    if (Partial2.Part.Lo > Dividend.Part.Lo)
                    {
                        Quotient.Part.Lo--;
                        Remainder.Full -= Divisor.Full;
                    }
                }
                else
                {
                    Quotient.Part.Lo--;
                    Remainder.Full -= Divisor.Full;
                }
            }
            Remainder.Full = Remainder.Full - Dividend.Full;
            Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi);
            Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo);
            if (Remainder.Part.Lo)
            {
                Remainder.Part.Hi--;
            }
        }
    }
    if (OutQuotient)
    {
        *OutQuotient = Quotient.Full;
    }
    if (OutRemainder)
    {
        *OutRemainder = Remainder.Full;
    }
    return_ACPI_STATUS (AE_OK);
}
ACPI_STATUS AcpiUtDivide ( UINT64 InDividend , UINT64 InDivisor , UINT64 * OutQuotient , UINT64 * OutRemainder ) { UINT64_OVERLAY Dividend ; UINT64_OVERLAY Divisor ; UINT64_OVERLAY Quotient ; UINT64_OVERLAY Remainder ; UINT64_OVERLAY NormalizedDividend ; UINT64_OVERLAY NormalizedDivisor ; UINT32 Partial1 ; UINT64_OVERLAY Partial2 ; UINT64_OVERLAY Partial3 ; ACPI_FUNCTION_TRACE ( UtDivide ) ; if ( InDivisor == 0 ) { ACPI_ERROR ( ( AE_INFO , " " ) ) ; return_ACPI_STATUS ( AE_AML_DIVIDE_BY_ZERO ) ; } Divisor . Full = InDivisor ; Dividend . Full = InDividend ; if ( Divisor . Part . Hi == 0 ) { Remainder . Part . Hi = 0 ; ACPI_DIV_64_BY_32 ( 0 , Dividend . Part . Hi , Divisor . Part . Lo , Quotient . Part . Hi , Partial1 ) ; ACPI_DIV_64_BY_32 ( Partial1 , Dividend . Part . Lo , Divisor . Part . Lo , Quotient . Part . Lo , Remainder . Part . Lo ) ; } else { Quotient . Part . Hi = 0 ; NormalizedDividend = Dividend ; NormalizedDivisor = Divisor ; do { ACPI_SHIFT_RIGHT_64 ( NormalizedDivisor . Part . Hi , NormalizedDivisor . Part . Lo ) ; ACPI_SHIFT_RIGHT_64 ( NormalizedDividend . Part . Hi , NormalizedDividend . Part . Lo ) ; } while ( NormalizedDivisor . Part . Hi != 0 ) ; ACPI_DIV_64_BY_32 ( NormalizedDividend . Part . Hi , NormalizedDividend . Part . Lo , NormalizedDivisor . Part . Lo , Quotient . Part . Lo , Partial1 ) ; Partial1 = Quotient . Part . Lo * Divisor . Part . Hi ; Partial2 . Full = ( UINT64 ) Quotient . Part . Lo * Divisor . Part . Lo ; Partial3 . Full = ( UINT64 ) Partial2 . Part . Hi + Partial1 ; Remainder . Part . Hi = Partial3 . Part . Lo ; Remainder . Part . Lo = Partial2 . Part . Lo ; if ( Partial3 . Part . Hi == 0 ) { if ( Partial3 . Part . Lo >= Dividend . Part . Hi ) { if ( Partial3 . Part . Lo == Dividend . Part . Hi ) { if ( Partial2 . Part . Lo > Dividend . Part . Lo ) { Quotient . Part . Lo -- ; Remainder . Full -= Divisor . Full ; } } else { Quotient . Part . Lo -- ; Remainder . Full -= Divisor . Full ; } } Remainder . Full = Remainder . Full - Dividend . Full ; Remainder . Part . Hi = ( UINT32 ) - ( ( INT32 ) Remainder . Part . Hi ) ; Remainder . Part . Lo = ( UINT32 ) - ( ( INT32 ) Remainder . Part . Lo ) ; if ( Remainder . Part . Lo ) { Remainder . Part . Hi -- ; } } } if ( OutQuotient ) { * OutQuotient = Quotient . Full ; } if ( OutRemainder ) { * OutRemainder = Remainder . Full ; } return_ACPI_STATUS ( AE_OK ) ; }
FUNCTION:    AcpiUtDivide
 PARAMETERS:  InDividend          - Dividend
              InDivisor           - Divisor
              OutQuotient         - Pointer to where the quotient is returned
              OutRemainder        - Pointer to where the remainder is returned
FUNCTION : AcpiUtDivide PARAMETERS : InDividend - Dividend InDivisor - Divisor OutQuotient - Pointer to where the quotient is returned OutRemainder - Pointer to where the remainder is returned
/* Always check for a zero divisor */ /*
         * 1) Simplest case is where the divisor is 32 bits, we can
         * just do two divides
         */ /*
         * The quotient is 64 bits, the remainder is always 32 bits,
         * and is generated by the second divide.
         */ /*
         * 2) The general case where the divisor is a full 64 bits
         * is more difficult
         */ /* Normalize the operands (shift until the divisor is < 32 bits) */ /* Partial divide */ /*
         * The quotient is always 32 bits, and simply requires
         * adjustment. The 64-bit remainder must be generated.
         */ /* Return only what was requested */