mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 07:50:15 +00:00
fixup! BitUtils
This commit is contained in:
parent
28d3c09df9
commit
559afdaecf
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user