fixup! BitUtils

This commit is contained in:
MerryMage 2016-04-06 21:01:05 +01:00
parent 28d3c09df9
commit 559afdaecf
4 changed files with 38 additions and 25 deletions

View File

@ -2,31 +2,44 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <climits>
#include <cstddef>
#include <type_traits>
namespace BitUtil {
/// Extract bits [begin_bit, end_bit] inclusive from s of type T.
template<size_t begin_bit, size_t end_bit, typename T>
constexpr T Bits(T s) {
static_assert(begin_bit <= end_bit, "bit range must begin before it ends");
static_assert(begin_bit < sizeof(s) * 8, "begin_bit must be smaller than size of T");
static_assert(end_bit < sizeof(s) * 8, "begin_bit must be smaller than size of T");
return (s >> begin_bit) & ((1 << (end_bit - begin_bit + 1)) - 1);
/// The size of a type in terms of bits
template <typename T>
constexpr size_t BitSize() {
return sizeof(T) * CHAR_BIT;
}
/// Sign-extends a val of type T that has NBits bits.
/// Extract bits [begin_bit, end_bit] inclusive from val of type T.
template<size_t begin_bit, size_t end_bit, typename T>
constexpr T Bits(const T value) {
static_assert(begin_bit <= end_bit, "bit range must begin before it ends");
static_assert(begin_bit < BitSize<T>(), "begin_bit must be smaller than size of T");
static_assert(end_bit < BitSize<T>(), "begin_bit must be smaller than size of T");
return (value >> begin_bit) & ((1 << (end_bit - begin_bit + 1)) - 1);
}
/// Extracts a single bit at bit_position from val of type T.
template<size_t bit_position, typename T>
constexpr T Bit(const T value) {
return Bits<bit_position, bit_position, T>(value);
}
/// Sign-extends a val that has NBits bits to the full bitwidth of type T.
template<size_t NBits, typename T>
inline T SignExtend(const T val) {
static_assert(std::is_signed<T>(), "T must be signed");
static_assert(NBits <= 8 * sizeof(T), "NBits larger that bitsize of T");
inline T SignExtend(const T value) {
static_assert(NBits <= BitSize<T>(), "NBits larger that bitsize of T");
using unsignedT = typename std::make_unsigned<T>::type;
constexpr size_t shift = 8 * sizeof(T) - NBits;
return static_cast<T>(static_cast<unsignedT>(val) << shift) >> shift;
constexpr T mask = static_cast<T>(1ULL << NBits) - 1;
const T signbit = (value >> NBits) & 1;
if (signbit != 0) {
return value | ~mask;
}
return value;
}
} // namespace BitUtil

View File

@ -519,7 +519,7 @@ std::string ARM_Disasm::DisassembleBLX(u32 insn)
if ((insn & 0xFE000000) == 0xFA000000) {
u32 imm24 = insn & 0xFFFFFF;
u32 H = (insn >> 24) & 1;
s32 offset = BitUtil::SignExtend<26, s32>((imm24 << 2) + (H << 1)) + 8;
s32 offset = BitUtil::SignExtend<26>((imm24 << 2) + (H << 1)) + 8;
return Common::StringFromFormat("blx\t#+%d", offset);
} else if ((insn & 0x0FFFFFF0) == 0x012FFF30) {
u8 cond = (insn >> 28) & 0xf;

View File

@ -13,7 +13,7 @@ using namespace Gen;
void JitX64::B(Cond cond, ArmImm24 imm24) {
cond_manager.CompileCond(cond);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(imm24 << 2);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26>(imm24 << 2);
reg_alloc.FlushEverything();
current.arm_pc += GetInstSize();
@ -28,7 +28,7 @@ void JitX64::B(Cond cond, ArmImm24 imm24) {
void JitX64::BL(Cond cond, ArmImm24 imm24) {
cond_manager.CompileCond(cond);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(imm24 << 2);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26>(imm24 << 2);
ASSERT(!current.TFlag);
const u32 link_pc = current.arm_pc + GetInstSize();
@ -49,7 +49,7 @@ void JitX64::BL(Cond cond, ArmImm24 imm24) {
void JitX64::BLX_imm(bool H, ArmImm24 imm24) {
cond_manager.Always();
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(imm24 << 2) + (H ? 2 : 0);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26>(imm24 << 2) + (H ? 2 : 0);
ASSERT(!current.TFlag);
const u32 link_pc = current.arm_pc + GetInstSize();

View File

@ -16,7 +16,7 @@ void JitX64::thumb_B(Cond cond, ArmImm8 imm8) {
ASSERT_MSG(current.TFlag, "thumb_B may only be called in thumb mode");
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<9, s32>(imm8 << 1);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<9>(imm8 << 1);
reg_alloc.FlushEverything();
current.arm_pc += GetInstSize();
@ -33,7 +33,7 @@ void JitX64::thumb_B(ArmImm11 imm11) {
ASSERT_MSG(current.TFlag, "thumb_B may only be called in thumb mode");
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<12, s32>(imm11 << 1);
const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<12>(imm11 << 1);
reg_alloc.FlushEverything();
current.arm_pc += GetInstSize();
@ -73,11 +73,11 @@ void JitX64::thumb_BLX_suffix(bool X, ArmImm11 imm11) {
ASSERT_MSG(current.TFlag, "thumb_BLX_suffix should only be called in thumb mode, pc = %u", current.arm_pc);
u32 new_pc = (current.arm_pc + 2) +
BitUtil::SignExtend<23, s32>(thumb_BLX_prefix_imm11 << 12) +
BitUtil::SignExtend<23>(thumb_BLX_prefix_imm11 << 12) +
(imm11 << 1);
u32 new_lr = (current.arm_pc + 2) | 1;
Gen::OpArg LR = reg_alloc.LockArmForWrite(ArmReg::LR);
OpArg LR = reg_alloc.LockArmForWrite(ArmReg::LR);
code->MOV(32, LR, Imm32(new_lr));
reg_alloc.UnlockArm(ArmReg::LR);