mirror of
https://github.com/fadden/6502bench.git
synced 2024-10-31 19:04:44 +00:00
113 lines
4.4 KiB
C#
113 lines
4.4 KiB
C#
/*
|
|
* Copyright 2019 faddenSoft
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
using System;
|
|
|
|
namespace CommonUtil {
|
|
/// <summary>
|
|
/// Some bit-twiddling functions.
|
|
/// </summary>
|
|
public static class BitTwiddle {
|
|
/// <summary>
|
|
/// Returns the argument, rounded up to the next highest power of 2. If the argument
|
|
/// is an exact power of two, it is returned unmodified.
|
|
/// </summary>
|
|
public static int RoundUpPowerOf2(int val) {
|
|
val--; // handle exact power of 2 case; works correctly for val=0
|
|
return NextHighestPowerOf2(val);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the first power of 2 value that is higher than val. If the argument is
|
|
/// an exact power of two, the next power of 2 is returned.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Classic bit-twiddling approach. I can't find a "count leading zeroes" function
|
|
/// in C# that turns into a CPU instruction; if we had that, we could just use 1<<N.
|
|
/// </remarks>
|
|
public static int NextHighestPowerOf2(int val) {
|
|
val |= val >> 1; // "smear" bits across integer
|
|
val |= val >> 2;
|
|
val |= val >> 4;
|
|
val |= val >> 8;
|
|
val |= val >> 16;
|
|
return val + 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an integer in which the only bit set is the least-significant set bit in
|
|
/// the argument.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// If you pass in 10110100, this will return 00000100.
|
|
///
|
|
/// Two's complement negation inverts and adds one, so 01100 --> 10011+1 --> 10100.
|
|
/// The only set bit they have in common is the one we want.
|
|
/// </remarks>
|
|
public static int IsolateLeastSignificantOne(int val) {
|
|
return val & -val;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the number of bits that are set in the argument.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// If you pass in 10110100, this will return 4.
|
|
///
|
|
/// This comes from http://aggregate.org/MAGIC/#Population%20Count%20(Ones%20Count) .
|
|
/// </remarks>
|
|
public static int CountOneBits(int val) {
|
|
// 32-bit recursive reduction using SWAR...
|
|
// but first step is mapping 2-bit values
|
|
// into sum of 2 1-bit values in sneaky way
|
|
val -= ((val >> 1) & 0x55555555);
|
|
val = (((val >> 2) & 0x33333333) + (val & 0x33333333));
|
|
val = (((val >> 4) + val) & 0x0f0f0f0f);
|
|
val += (val >> 8);
|
|
val += (val >> 16);
|
|
return (val & 0x0000003f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the number of trailing zero bits in the argument.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// If you pass in 10110100, this will return 2.
|
|
///
|
|
/// Also from http://aggregate.org/MAGIC/ .
|
|
/// </remarks>
|
|
public static int CountTrailingZeroes(int val) {
|
|
// Lazy: reduce to least-significant 1 bit, subtract one to clear that bit and set
|
|
// all the bits to the right of it, then just count the 1s.
|
|
return CountOneBits(IsolateLeastSignificantOne(val) - 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sign-extends an integer value.
|
|
/// </summary>
|
|
/// <param name="val">Value to extend.</param>
|
|
/// <param name="byteLen">Number of significant bytes (1-4).</param>
|
|
/// <returns>Sign-extended value, or original value if byteLen is invalid.</returns>
|
|
public static int SignExtend(int val, int byteLen) {
|
|
if (byteLen < 1 || byteLen >= 4) {
|
|
// invalid, or nothing to do
|
|
return val;
|
|
}
|
|
int shiftCount = (4 - byteLen) * 8;
|
|
return (val << shiftCount) >> shiftCount;
|
|
}
|
|
}
|
|
}
|