184493Smsmith/******************************************************************************* 284493Smsmith * 384493Smsmith * Module Name: utmath - Integer math support routines 484493Smsmith * 584493Smsmith ******************************************************************************/ 684493Smsmith 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, Intel Corp. 984493Smsmith * All rights reserved. 1084493Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2584493Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2984493Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4384493Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 4684493Smsmith 4784493Smsmith 4884493Smsmith#define _COMPONENT ACPI_UTILITIES 4991116Smsmith ACPI_MODULE_NAME ("utmath") 5084493Smsmith 5184493Smsmith/* 52212761Sjkim * Optional support for 64-bit double-precision integer divide. This code 53212761Sjkim * is configurable and is implemented in order to support 32-bit kernel 54212761Sjkim * environments where a 64-bit double-precision math library is not available. 55212761Sjkim * 56212761Sjkim * Support for a more normal 64-bit divide/modulo (with check for a divide- 57212761Sjkim * by-zero) appears after this optional section of code. 5884493Smsmith */ 59212761Sjkim#ifndef ACPI_USE_NATIVE_DIVIDE 6084493Smsmith 61212761Sjkim/* Structures used only for 64-bit divide */ 62212761Sjkim 63212761Sjkimtypedef struct uint64_struct 64212761Sjkim{ 65212761Sjkim UINT32 Lo; 66212761Sjkim UINT32 Hi; 67212761Sjkim 68212761Sjkim} UINT64_STRUCT; 69212761Sjkim 70212761Sjkimtypedef union uint64_overlay 71212761Sjkim{ 72212761Sjkim UINT64 Full; 73212761Sjkim UINT64_STRUCT Part; 74212761Sjkim 75212761Sjkim} UINT64_OVERLAY; 76212761Sjkim 77212761Sjkim 7884493Smsmith/******************************************************************************* 7984493Smsmith * 8084493Smsmith * FUNCTION: AcpiUtShortDivide 8184493Smsmith * 82138287Smarks * PARAMETERS: Dividend - 64-bit dividend 8384493Smsmith * Divisor - 32-bit divisor 8484493Smsmith * OutQuotient - Pointer to where the quotient is returned 8584493Smsmith * OutRemainder - Pointer to where the remainder is returned 8684493Smsmith * 8784493Smsmith * RETURN: Status (Checks for divide-by-zero) 8884493Smsmith * 8984493Smsmith * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) 90241973Sjkim * divide and modulo. The result is a 64-bit quotient and a 9184493Smsmith * 32-bit remainder. 9284493Smsmith * 9384493Smsmith ******************************************************************************/ 9484493Smsmith 9584493SmsmithACPI_STATUS 9684493SmsmithAcpiUtShortDivide ( 97202771Sjkim UINT64 Dividend, 9884493Smsmith UINT32 Divisor, 99202771Sjkim UINT64 *OutQuotient, 10084493Smsmith UINT32 *OutRemainder) 10184493Smsmith{ 102138287Smarks UINT64_OVERLAY DividendOvl; 10384493Smsmith UINT64_OVERLAY Quotient; 10484493Smsmith UINT32 Remainder32; 10584493Smsmith 10684493Smsmith 107167802Sjkim ACPI_FUNCTION_TRACE (UtShortDivide); 10884493Smsmith 10984493Smsmith 11084493Smsmith /* Always check for a zero divisor */ 11184493Smsmith 11284493Smsmith if (Divisor == 0) 11384493Smsmith { 114167802Sjkim ACPI_ERROR ((AE_INFO, "Divide by zero")); 11584493Smsmith return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); 11684493Smsmith } 11784493Smsmith 118138287Smarks DividendOvl.Full = Dividend; 119138287Smarks 12084493Smsmith /* 12184493Smsmith * The quotient is 64 bits, the remainder is always 32 bits, 12284493Smsmith * and is generated by the second divide. 12384493Smsmith */ 124138287Smarks ACPI_DIV_64_BY_32 (0, DividendOvl.Part.Hi, Divisor, 12584493Smsmith Quotient.Part.Hi, Remainder32); 126138287Smarks ACPI_DIV_64_BY_32 (Remainder32, DividendOvl.Part.Lo, Divisor, 12784493Smsmith Quotient.Part.Lo, Remainder32); 12884493Smsmith 12984493Smsmith /* Return only what was requested */ 13084493Smsmith 13184493Smsmith if (OutQuotient) 13284493Smsmith { 13384493Smsmith *OutQuotient = Quotient.Full; 13484493Smsmith } 13584493Smsmith if (OutRemainder) 13684493Smsmith { 13784493Smsmith *OutRemainder = Remainder32; 13884493Smsmith } 13984493Smsmith 14084493Smsmith return_ACPI_STATUS (AE_OK); 14184493Smsmith} 14284493Smsmith 14384493Smsmith 14484493Smsmith/******************************************************************************* 14584493Smsmith * 14684493Smsmith * FUNCTION: AcpiUtDivide 14784493Smsmith * 148138287Smarks * PARAMETERS: InDividend - Dividend 149138287Smarks * InDivisor - Divisor 15084493Smsmith * OutQuotient - Pointer to where the quotient is returned 15184493Smsmith * OutRemainder - Pointer to where the remainder is returned 15284493Smsmith * 15384493Smsmith * RETURN: Status (Checks for divide-by-zero) 15484493Smsmith * 15584493Smsmith * DESCRIPTION: Perform a divide and modulo. 15684493Smsmith * 15784493Smsmith ******************************************************************************/ 15884493Smsmith 15984493SmsmithACPI_STATUS 16084493SmsmithAcpiUtDivide ( 161202771Sjkim UINT64 InDividend, 162202771Sjkim UINT64 InDivisor, 163202771Sjkim UINT64 *OutQuotient, 164202771Sjkim UINT64 *OutRemainder) 16584493Smsmith{ 16684493Smsmith UINT64_OVERLAY Dividend; 16784493Smsmith UINT64_OVERLAY Divisor; 16884493Smsmith UINT64_OVERLAY Quotient; 16984493Smsmith UINT64_OVERLAY Remainder; 17084493Smsmith UINT64_OVERLAY NormalizedDividend; 17184493Smsmith UINT64_OVERLAY NormalizedDivisor; 17284493Smsmith UINT32 Partial1; 17384493Smsmith UINT64_OVERLAY Partial2; 17484493Smsmith UINT64_OVERLAY Partial3; 17584493Smsmith 17684493Smsmith 177167802Sjkim ACPI_FUNCTION_TRACE (UtDivide); 17884493Smsmith 17984493Smsmith 18084493Smsmith /* Always check for a zero divisor */ 18184493Smsmith 182138287Smarks if (InDivisor == 0) 18384493Smsmith { 184167802Sjkim ACPI_ERROR ((AE_INFO, "Divide by zero")); 18584493Smsmith return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); 18684493Smsmith } 18784493Smsmith 188138287Smarks Divisor.Full = InDivisor; 189138287Smarks Dividend.Full = InDividend; 19084493Smsmith if (Divisor.Part.Hi == 0) 19184493Smsmith { 19284493Smsmith /* 19384493Smsmith * 1) Simplest case is where the divisor is 32 bits, we can 19484493Smsmith * just do two divides 19584493Smsmith */ 19684493Smsmith Remainder.Part.Hi = 0; 19784493Smsmith 19884493Smsmith /* 19984493Smsmith * The quotient is 64 bits, the remainder is always 32 bits, 20084493Smsmith * and is generated by the second divide. 20184493Smsmith */ 20287031Smsmith ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo, 20384493Smsmith Quotient.Part.Hi, Partial1); 20487031Smsmith ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo, 20584493Smsmith Quotient.Part.Lo, Remainder.Part.Lo); 20684493Smsmith } 20784493Smsmith 20884493Smsmith else 20984493Smsmith { 21084493Smsmith /* 21184493Smsmith * 2) The general case where the divisor is a full 64 bits 21284493Smsmith * is more difficult 21384493Smsmith */ 21484493Smsmith Quotient.Part.Hi = 0; 21584493Smsmith NormalizedDividend = Dividend; 21684493Smsmith NormalizedDivisor = Divisor; 21784493Smsmith 21884493Smsmith /* Normalize the operands (shift until the divisor is < 32 bits) */ 21984493Smsmith 22084493Smsmith do 22184493Smsmith { 22287031Smsmith ACPI_SHIFT_RIGHT_64 (NormalizedDivisor.Part.Hi, 22384493Smsmith NormalizedDivisor.Part.Lo); 22487031Smsmith ACPI_SHIFT_RIGHT_64 (NormalizedDividend.Part.Hi, 22584493Smsmith NormalizedDividend.Part.Lo); 22684493Smsmith 22784493Smsmith } while (NormalizedDivisor.Part.Hi != 0); 22884493Smsmith 22984493Smsmith /* Partial divide */ 23084493Smsmith 23187031Smsmith ACPI_DIV_64_BY_32 (NormalizedDividend.Part.Hi, 23287031Smsmith NormalizedDividend.Part.Lo, 23387031Smsmith NormalizedDivisor.Part.Lo, 23484493Smsmith Quotient.Part.Lo, Partial1); 23584493Smsmith 23684493Smsmith /* 23784493Smsmith * The quotient is always 32 bits, and simply requires adjustment. 23884493Smsmith * The 64-bit remainder must be generated. 23984493Smsmith */ 24084493Smsmith Partial1 = Quotient.Part.Lo * Divisor.Part.Hi; 241202771Sjkim Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo; 242202771Sjkim Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1; 24384493Smsmith 24484493Smsmith Remainder.Part.Hi = Partial3.Part.Lo; 24584493Smsmith Remainder.Part.Lo = Partial2.Part.Lo; 24684493Smsmith 24784493Smsmith if (Partial3.Part.Hi == 0) 24884493Smsmith { 24984493Smsmith if (Partial3.Part.Lo >= Dividend.Part.Hi) 25084493Smsmith { 25184493Smsmith if (Partial3.Part.Lo == Dividend.Part.Hi) 25284493Smsmith { 25384493Smsmith if (Partial2.Part.Lo > Dividend.Part.Lo) 25484493Smsmith { 25584493Smsmith Quotient.Part.Lo--; 25684493Smsmith Remainder.Full -= Divisor.Full; 25784493Smsmith } 25884493Smsmith } 25984493Smsmith else 26084493Smsmith { 26184493Smsmith Quotient.Part.Lo--; 26284493Smsmith Remainder.Full -= Divisor.Full; 26384493Smsmith } 26484493Smsmith } 26584493Smsmith 26684493Smsmith Remainder.Full = Remainder.Full - Dividend.Full; 26799679Siwasaki Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi); 26899679Siwasaki Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo); 26984493Smsmith 27084493Smsmith if (Remainder.Part.Lo) 27184493Smsmith { 27284493Smsmith Remainder.Part.Hi--; 27384493Smsmith } 27484493Smsmith } 27584493Smsmith } 27684493Smsmith 27784493Smsmith /* Return only what was requested */ 27884493Smsmith 27984493Smsmith if (OutQuotient) 28084493Smsmith { 28184493Smsmith *OutQuotient = Quotient.Full; 28284493Smsmith } 28384493Smsmith if (OutRemainder) 28484493Smsmith { 28584493Smsmith *OutRemainder = Remainder.Full; 28684493Smsmith } 28784493Smsmith 28884493Smsmith return_ACPI_STATUS (AE_OK); 28984493Smsmith} 29084493Smsmith 29184493Smsmith#else 29284493Smsmith 29384493Smsmith/******************************************************************************* 29484493Smsmith * 29584493Smsmith * FUNCTION: AcpiUtShortDivide, AcpiUtDivide 29684493Smsmith * 297151937Sjkim * PARAMETERS: See function headers above 298151937Sjkim * 29984493Smsmith * DESCRIPTION: Native versions of the UtDivide functions. Use these if either 30084493Smsmith * 1) The target is a 64-bit platform and therefore 64-bit 30184493Smsmith * integer math is supported directly by the machine. 30287031Smsmith * 2) The target is a 32-bit or 16-bit platform, and the 30387031Smsmith * double-precision integer math library is available to 30484493Smsmith * perform the divide. 30584493Smsmith * 30684493Smsmith ******************************************************************************/ 30784493Smsmith 30884493SmsmithACPI_STATUS 30984493SmsmithAcpiUtShortDivide ( 310202771Sjkim UINT64 InDividend, 31184493Smsmith UINT32 Divisor, 312202771Sjkim UINT64 *OutQuotient, 31384493Smsmith UINT32 *OutRemainder) 31484493Smsmith{ 31584493Smsmith 316167802Sjkim ACPI_FUNCTION_TRACE (UtShortDivide); 31784493Smsmith 31884493Smsmith 31984493Smsmith /* Always check for a zero divisor */ 32084493Smsmith 32184493Smsmith if (Divisor == 0) 32284493Smsmith { 323167802Sjkim ACPI_ERROR ((AE_INFO, "Divide by zero")); 32484493Smsmith return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); 32584493Smsmith } 32684493Smsmith 32784493Smsmith /* Return only what was requested */ 32884493Smsmith 32984493Smsmith if (OutQuotient) 33084493Smsmith { 331138287Smarks *OutQuotient = InDividend / Divisor; 33284493Smsmith } 33384493Smsmith if (OutRemainder) 33484493Smsmith { 335193267Sjkim *OutRemainder = (UINT32) (InDividend % Divisor); 33684493Smsmith } 33784493Smsmith 33884493Smsmith return_ACPI_STATUS (AE_OK); 33984493Smsmith} 34084493Smsmith 34184493SmsmithACPI_STATUS 34284493SmsmithAcpiUtDivide ( 343202771Sjkim UINT64 InDividend, 344202771Sjkim UINT64 InDivisor, 345202771Sjkim UINT64 *OutQuotient, 346202771Sjkim UINT64 *OutRemainder) 34784493Smsmith{ 348167802Sjkim ACPI_FUNCTION_TRACE (UtDivide); 34984493Smsmith 35084493Smsmith 35184493Smsmith /* Always check for a zero divisor */ 35284493Smsmith 353138287Smarks if (InDivisor == 0) 35484493Smsmith { 355167802Sjkim ACPI_ERROR ((AE_INFO, "Divide by zero")); 35684493Smsmith return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); 35784493Smsmith } 35884493Smsmith 35984493Smsmith 36084493Smsmith /* Return only what was requested */ 36184493Smsmith 36284493Smsmith if (OutQuotient) 36384493Smsmith { 364138287Smarks *OutQuotient = InDividend / InDivisor; 36584493Smsmith } 36684493Smsmith if (OutRemainder) 36784493Smsmith { 368138287Smarks *OutRemainder = InDividend % InDivisor; 36984493Smsmith } 37084493Smsmith 37185756Smsmith return_ACPI_STATUS (AE_OK); 37284493Smsmith} 37384493Smsmith 37484493Smsmith#endif 375