dmose%mozilla.org 2ccab49e6d updating license boilerplate to xPL v1.1
git-svn-id: svn://10.0.0.236/trunk@52526 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 06:38:29 +00:00

265 lines
8.0 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "Fundamentals.h"
#include "prbit.h"
#include "HPPAMul.h"
/*
*-----------------------------------------------------------------------
*
* Local data for an HPPA proc. This should be obtained by asking the
* Code Generator to fill these arrays.
*
*-----------------------------------------------------------------------
*/
static PRInt16 shiftCosts[32] =
{
0, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4
};
static PRInt16 shiftAddCosts[32] =
{
4, 4, 4, 4, 999, 999, 999, 999,
999, 999, 999, 999, 999, 999, 999, 999,
999, 999, 999, 999, 999, 999, 999, 999,
999, 999, 999, 999, 999, 999, 999, 999
};
static PRInt16 shiftSubCosts[32] =
{
4, 999, 999, 999, 999, 999, 999, 999,
999, 999, 999, 999, 999, 999, 999, 999,
999, 999, 999, 999, 999, 999, 999, 999,
999, 999, 999, 999, 999, 999, 999, 999
};
static PRInt16 addCost = 4;
/*
*-----------------------------------------------------------------------
*
* getMulAlgorithm --
*
* Return the best algorithm for an immediate multiplication.
* If algorithm.cost >= maxCost or retval is false then no algorithm
* was found and a regular multiplication should be used.
*
* This algorithm does not work if the register to multiply is larger
* than an PRUint32 and the multiplicand does not fit exactely in an PRUint32.
* e.g.: long long mul by a negative value.
*
*-----------------------------------------------------------------------
*/
bool
getMulAlgorithm(MulAlgorithm* algorithm, PRUint32 multiplicand, PRInt16 maxCost)
{
PRUint32 mask;
PRUint8 currentCost;
PRInt8 shiftBy;
algorithm->cost = maxCost;
if (maxCost <= 0)
return false;
if (multiplicand == 0x1)
{
algorithm->nOperations = 1;
algorithm->cost = 0;
algorithm->operations[0] = maMultiplicand;
return true;
}
if (multiplicand == 0x0)
{
algorithm->nOperations = 1;
algorithm->cost = 0;
algorithm->operations[0] = maZero;
return true;
}
MulAlgorithm* downAlgorithm = new MulAlgorithm();
MulAlgorithm* bestAlgorithm = new MulAlgorithm();
MulAlgorithm* swapAlgorithm;
// we try to do a shift if there is a group of 0 bits.
if ((multiplicand & 0x1) == 0x0)
{
// number of low zero bits.
mask = multiplicand & -multiplicand;
PR_FLOOR_LOG2(shiftBy, mask);
currentCost = shiftCosts[shiftBy];
getMulAlgorithm(downAlgorithm, multiplicand >> shiftBy, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = shiftBy;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maShiftValue;
maxCost = currentCost;
}
}
// If this is an odd number, we can try to add one or to subtract one.
if ((multiplicand & 0x1) != 0x0)
{
for (mask = 1; (mask & multiplicand) != 0x0; mask <<= 1);
if (mask > 2 && multiplicand != 3)
{
currentCost = addCost;
getMulAlgorithm(downAlgorithm, multiplicand + 1, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = 0;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maSubShiftMultiplicandFromValue;
maxCost = currentCost;
}
}
else
{
currentCost = addCost;
getMulAlgorithm(downAlgorithm, multiplicand - 1, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = 0;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maAddValueToShiftMultiplicand;
maxCost = currentCost;
}
}
}
mask = multiplicand - 1;
PR_FLOOR_LOG2(shiftBy, mask);
while (shiftBy >= 2)
{
PRUint32 d;
d = (0x1 << shiftBy) + 1;
if (multiplicand % d == 0 && multiplicand > d)
{
currentCost = PR_MIN(shiftAddCosts[shiftBy], addCost + shiftCosts[shiftBy]);
getMulAlgorithm(downAlgorithm, multiplicand / d, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = shiftBy;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maAddValueToShiftValue;
maxCost = currentCost;
}
break;
}
d = (0x1 << shiftBy) - 1;
if (multiplicand % d == 0 && multiplicand > d)
{
currentCost = PR_MIN(shiftSubCosts[shiftBy], addCost + shiftCosts[shiftBy]);
getMulAlgorithm(downAlgorithm, multiplicand / d, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = shiftBy;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maSubValueFromShiftValue;
maxCost = currentCost;
}
break;
}
shiftBy--;
}
if ((multiplicand & 0x1) != 0x0)
{
mask = multiplicand - 1;
mask = mask & -mask;
if (mask != 0 && (mask & (mask - 1)) == 0)
{
PR_FLOOR_LOG2(shiftBy, mask);
currentCost = shiftAddCosts[shiftBy];
getMulAlgorithm(downAlgorithm, (multiplicand - 1) >> shiftBy, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = shiftBy;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maAddMultiplicandToShiftValue;
maxCost = currentCost;
}
}
mask = multiplicand + 1;
mask = mask & -mask;
if (mask != 0 && (mask & (mask - 1)) == 0)
{
PR_FLOOR_LOG2(shiftBy, mask);
currentCost = shiftSubCosts[shiftBy];
getMulAlgorithm(downAlgorithm, (multiplicand + 1) >> shiftBy, maxCost - currentCost);
currentCost += downAlgorithm->cost;
if (currentCost < maxCost)
{
swapAlgorithm = downAlgorithm, downAlgorithm = bestAlgorithm, bestAlgorithm = swapAlgorithm;
bestAlgorithm->shiftAmount[bestAlgorithm->nOperations] = shiftBy;
bestAlgorithm->operations[bestAlgorithm->nOperations] = maSubMultiplicandFromShiftValue;
maxCost = currentCost;
}
}
}
// No algorithm found.
if (maxCost == algorithm->cost)
return false;
// Too long
if (bestAlgorithm->nOperations == 32)
return false;
algorithm->nOperations = bestAlgorithm->nOperations + 1;
algorithm->cost = maxCost;
copy(bestAlgorithm->operations, &bestAlgorithm->operations[algorithm->nOperations], algorithm->operations);
copy(bestAlgorithm->shiftAmount, &bestAlgorithm->shiftAmount[algorithm->nOperations], algorithm->shiftAmount);
// we better find a way to avoid allocating memory each time.
delete downAlgorithm;
delete bestAlgorithm;
return true;
}