mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 09: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
|
// 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
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user