From 607ce603f280a101f869adf591fe1032353636bd Mon Sep 17 00:00:00 2001 From: Samuel Huang Date: Wed, 13 Jun 2018 17:47:39 +0000 Subject: [Zucchini] Introduce bit operations into algorithm.h. This CL makes algorithm.h in Chromium match trunk's version. Details: - Add {GetBit(), GetSignedBits(), GetUnsignedBits(), SignedFit()}. These will be used by the ARM Disassembler. - Rename ceil() to AlignCeil() to avoid confusion with ceil() from . - Extensive unit tests. - Minor enum type fix in disassembler_win32.h (offset_t should not be used to represent lengths). Change-Id: Icf9ce254bce2e5a3e9c286dbb5a704aeacd8bc35 Reviewed-on: https://chromium-review.googlesource.com/1098556 Reviewed-by: Samuel Huang Reviewed-by: Greg Thompson Commit-Queue: Samuel Huang Cr-Commit-Position: refs/heads/master@{#566893} NOKEYCHECK=True GitOrigin-RevId: 2c50b5af45fa271f06317419f6b8bfc5f4a80be0 --- algorithm.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'algorithm.h') diff --git a/algorithm.h b/algorithm.h index 7143a95..463aca3 100644 --- a/algorithm.h +++ b/algorithm.h @@ -48,7 +48,7 @@ T InclusiveClamp(T value, T lo, T hi) { // Returns the minimum multiple of |m| that's no less than |x|. Assumes |m > 0| // and |x| is sufficiently small so that no overflow occurs. template -constexpr T ceil(T x, T m) { +constexpr T AlignCeil(T x, T m) { static_assert(std::is_unsigned::value, "Value type must be unsigned."); return T((x + m - 1) / m) * m; } @@ -62,6 +62,47 @@ void SortAndUniquify(std::vector* container) { container->shrink_to_fit(); } +// Extracts a single bit at |pos| from integer |v|. +template +constexpr T GetBit(T v) { + return (v >> pos) & 1; +} + +// Extracts bits in inclusive range [|lo|, |hi|] from integer |v|, and returns +// the sign-extend result. For example, let the (MSB-first) bits in a 32-bit int +// |v| be: +// xxxxxxxx xxxxxSii iiiiiiii iyyyyyyy, +// hi^ lo^ => lo = 7, hi = 18 +// To extract "Sii iiiiiiii i", calling +// GetSignedBits<7, 18>(v); +// produces the sign-extended result: +// SSSSSSSS SSSSSSSS SSSSSiii iiiiiiii. +template +constexpr typename std::make_signed::type GetSignedBits(T v) { + constexpr int kNumBits = sizeof(T) * 8; + using SignedType = typename std::make_signed::type; + // Assumes 0 <= |lo| <= |hi| < |kNumBits|. + // How this works: + // (1) Shift-left by |kNumBits - 1 - hi| to clear "left" bits. + // (2) Shift-right by |kNumBits - 1 - hi + lo| to clear "right" bits. The + // input is casted to a signed type to perform sign-extension. + return static_cast(v << (kNumBits - 1 - hi)) >> + (kNumBits - 1 - hi + lo); +} + +// Similar to GetSignedBits(), but returns the zero-extended result. For the +// above example, calling +// GetUnsignedBits<7, 18>(v); +// results in: +// 00000000 00000000 0000Siii iiiiiiii. +template +constexpr typename std::make_unsigned::type GetUnsignedBits(T v) { + constexpr int kNumBits = sizeof(T) * 8; + using UnsignedType = typename std::make_unsigned::type; + return static_cast(v << (kNumBits - 1 - hi)) >> + (kNumBits - 1 - hi + lo); +} + // Copies bits at |pos| in |v| to all higher bits, and returns the result as the // same int type as |v|. template @@ -79,6 +120,13 @@ constexpr T SignExtend(T v) { return static_cast::type>(v << kShift) >> kShift; } +// Determines whether |v|, if interpreted as a signed integer, is representable +// using |digs| bits. |1 <= digs <= sizeof(T)| is assumed. +template +constexpr bool SignedFit(T v) { + return v == SignExtend(v); +} + } // namespace zucchini #endif // COMPONENTS_ZUCCHINI_ALGORITHM_H_ -- cgit v1.2.3