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

View File

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

View File

@ -13,7 +13,7 @@ using namespace Gen;
void JitX64::B(Cond cond, ArmImm24 imm24) { void JitX64::B(Cond cond, ArmImm24 imm24) {
cond_manager.CompileCond(cond); 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(); reg_alloc.FlushEverything();
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
@ -28,7 +28,7 @@ void JitX64::B(Cond cond, ArmImm24 imm24) {
void JitX64::BL(Cond cond, ArmImm24 imm24) { void JitX64::BL(Cond cond, ArmImm24 imm24) {
cond_manager.CompileCond(cond); 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); ASSERT(!current.TFlag);
const u32 link_pc = current.arm_pc + GetInstSize(); 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) { void JitX64::BLX_imm(bool H, ArmImm24 imm24) {
cond_manager.Always(); 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); ASSERT(!current.TFlag);
const u32 link_pc = current.arm_pc + GetInstSize(); 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"); 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(); reg_alloc.FlushEverything();
current.arm_pc += GetInstSize(); 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"); 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(); reg_alloc.FlushEverything();
current.arm_pc += GetInstSize(); 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); 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) + 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); (imm11 << 1);
u32 new_lr = (current.arm_pc + 2) | 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)); code->MOV(32, LR, Imm32(new_lr));
reg_alloc.UnlockArm(ArmReg::LR); reg_alloc.UnlockArm(ArmReg::LR);