144 lines
4.1 KiB
C
144 lines
4.1 KiB
C
/*********************************************************
|
|
* Copyright (C) 2003-2014 VMware, Inc. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation version 2.1 and no later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
|
* License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
*********************************************************/
|
|
|
|
/*********************************************************
|
|
* The contents of this file are subject to the terms of the Common
|
|
* Development and Distribution License (the "License") version 1.0
|
|
* and no later version. You may not use this file except in
|
|
* compliance with the License.
|
|
*
|
|
* You can obtain a copy of the License at
|
|
* http://www.opensource.org/licenses/cddl1.php
|
|
*
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* mul64.h
|
|
*
|
|
* Integer by fixed point multiplication, with rounding.
|
|
*
|
|
* These routines are implemented in assembly language for most
|
|
* supported platforms. This file has plain C fallback versions.
|
|
*/
|
|
|
|
#ifndef _MUL64_H_
|
|
#define _MUL64_H_
|
|
|
|
#define INCLUDE_ALLOW_USERLEVEL
|
|
|
|
#define INCLUDE_ALLOW_MODULE
|
|
#define INCLUDE_ALLOW_VMMON
|
|
#define INCLUDE_ALLOW_VMK_MODULE
|
|
#define INCLUDE_ALLOW_VMKERNEL
|
|
#define INCLUDE_ALLOW_DISTRIBUTE
|
|
#define INCLUDE_ALLOW_VMCORE
|
|
#include "includeCheck.h"
|
|
|
|
#include "vm_basic_asm.h"
|
|
|
|
#ifdef MUL64_NO_ASM
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* Mul64x3264 --
|
|
*
|
|
* Unsigned integer by fixed point multiplication, with rounding:
|
|
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
|
|
*
|
|
* Unsigned 64-bit integer multiplicand.
|
|
* Unsigned 32-bit fixed point multiplier, represented as
|
|
* (multiplier, shift), where shift < 64.
|
|
*
|
|
* Result:
|
|
* Unsigned 64-bit integer product.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
static INLINE uint64
|
|
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
|
|
{
|
|
uint64 lo, hi, lo2, hi2;
|
|
unsigned carry;
|
|
|
|
// ASSERT(shift >= 0 && shift < 64);
|
|
|
|
lo = (multiplicand & 0xffffffff) * multiplier;
|
|
hi = (multiplicand >> 32) * multiplier;
|
|
|
|
lo2 = lo + (hi << 32);
|
|
carry = lo2 < lo;
|
|
hi2 = (hi >> 32) + carry;
|
|
|
|
if (shift == 0) {
|
|
return lo2;
|
|
} else {
|
|
return (lo2 >> shift) + (hi2 << (64 - shift)) +
|
|
((lo2 >> (shift - 1)) & 1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* Muls64x32s64 --
|
|
*
|
|
* Signed integer by fixed point multiplication, with rounding:
|
|
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
|
|
*
|
|
* Signed 64-bit integer multiplicand.
|
|
* Unsigned 32-bit fixed point multiplier, represented as
|
|
* (multiplier, shift), where shift < 64.
|
|
*
|
|
* Result:
|
|
* Signed 64-bit integer product.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
static INLINE int64
|
|
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
|
|
{
|
|
uint64 lo, hi, lo2, hi2;
|
|
unsigned carry;
|
|
|
|
// ASSERT(shift >= 0 && shift < 64);
|
|
|
|
hi = ((uint64)multiplicand >> 32) * multiplier;
|
|
if (multiplicand < 0) {
|
|
hi -= (uint64)multiplier << 32;
|
|
}
|
|
lo = ((uint64)multiplicand & 0xffffffff) * multiplier;
|
|
|
|
lo2 = lo + (hi << 32);
|
|
carry = lo2 < lo;
|
|
hi2 = (((int64)hi >> 32) + carry);
|
|
|
|
if (shift == 0) {
|
|
return lo2;
|
|
} else {
|
|
return (lo2 >> shift) + (hi2 << (64 - shift)) +
|
|
((lo2 >> (shift - 1)) & 1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif // _MUL64_NOASM_H_
|
|
|