From 6ccde4718ee47393af82f4f6883d45556befe096 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Tue, 5 Apr 2016 09:34:00 +0100 Subject: [PATCH] fixup! Common: Move SignExtend and bits into BitUtil --- src/common/CMakeLists.txt | 1 + src/common/bit_util.h | 32 ++++ src/common/math_util.h | 12 -- src/core/arm/decoder/thumb.cpp | 150 +++++++++---------- src/core/arm/disassembler/arm_disasm.cpp | 4 +- src/core/arm/jit_x64/instructions/branch.cpp | 8 +- src/core/arm/jit_x64/instructions/thumb.cpp | 8 +- 7 files changed, 115 insertions(+), 100 deletions(-) create mode 100644 src/common/bit_util.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index c839ce173..014748125 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -26,6 +26,7 @@ set(HEADERS assert.h bit_field.h bit_set.h + bit_util.h break_points.h chunk_file.h code_block.h diff --git a/src/common/bit_util.h b/src/common/bit_util.h new file mode 100644 index 000000000..723fffa74 --- /dev/null +++ b/src/common/bit_util.h @@ -0,0 +1,32 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include + +namespace BitUtil { + +/// Extract bits [begin_bit, end_bit] inclusive from s of type T. +template +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); +} + +/// Sign-extends a val of type T that has NBits bits. +template +inline T SignExtend(const T val) { + static_assert(std::is_signed(), "T must be signed"); + static_assert(NBits <= 8 * sizeof(T), "NBits larger that bitsize of T"); + + using unsignedT = typename std::make_unsigned::type; + + constexpr size_t shift = 8 * sizeof(T) - NBits; + return static_cast(static_cast(val) << shift) >> shift; +} + +} // namespace BitUtil diff --git a/src/common/math_util.h b/src/common/math_util.h index fbcc09490..fc96d3641 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h @@ -21,18 +21,6 @@ inline T Clamp(const T val, const T& min, const T& max) { return std::max(min, std::min(max, val)); } -/// Sign-extends a val of type T that has NBits bits. -template -inline T SignExtend(const T val) { - static_assert(std::numeric_limits::is_signed, "T must be signed"); - static_assert(NBits <= 8 * sizeof(T), "NBits larger that bitsize of T"); - - using unsignedT = typename std::make_unsigned::type; - - constexpr size_t shift = 8 * sizeof(T) - NBits; - return static_cast(static_cast(val) << shift) >> shift; -} - template struct Rectangle { T left; diff --git a/src/core/arm/decoder/thumb.cpp b/src/core/arm/decoder/thumb.cpp index 4eb0e0a86..25bc0b34b 100644 --- a/src/core/arm/decoder/thumb.cpp +++ b/src/core/arm/decoder/thumb.cpp @@ -9,6 +9,7 @@ #include #include "common/assert.h" +#include "common/bit_util.h" #include "common/common_types.h" #include "common/make_unique.h" @@ -42,21 +43,14 @@ ThumbMatcher MakeMatcher(const char* const str, std::function -static 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); -} +using BitUtil::Bits; static const std::array thumb_instruction_table = { { { "LSL/LSR/ASR", MakeMatcher("000ooxxxxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<11, 12>(instruction); - u32 imm5 = bits<6, 10>(instruction); - Register Rm = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opcode = Bits<11, 12>(instruction); + u32 imm5 = Bits<6, 10>(instruction); + Register Rm = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opcode) { case 0: // LSL , , # v->MOV_reg(Cond::AL, /*S=*/true, Rd, imm5, ShiftType::LSL, Rm); @@ -72,10 +66,10 @@ static const std::array thumb_instruction_table = { { } })}, { "ADD/SUB_reg", MakeMatcher("000110oxxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<9, 9>(instruction); - Register Rm = static_cast(bits<6, 8>(instruction)); - Register Rn = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opcode = Bits<9, 9>(instruction); + Register Rm = static_cast(Bits<6, 8>(instruction)); + Register Rn = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opcode) { case 0: // ADD , , v->ADD_reg(Cond::AL, /*S=*/true, Rn, Rd, 0, ShiftType::LSL, Rm); @@ -88,10 +82,10 @@ static const std::array thumb_instruction_table = { { } })}, { "ADD/SUB_imm", MakeMatcher("000111oxxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<9, 9>(instruction); - u32 imm3 = bits<6, 8>(instruction); - Register Rn = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opcode = Bits<9, 9>(instruction); + u32 imm3 = Bits<6, 8>(instruction); + Register Rn = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opcode) { case 0: // ADD , , # v->ADD_imm(Cond::AL, /*S=*/true, Rn, Rd, 0, imm3); @@ -104,9 +98,9 @@ static const std::array thumb_instruction_table = { { } })}, { "add/sub/cmp/mov_imm", MakeMatcher("001ooxxxxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<11, 12>(instruction); - Register Rd = static_cast(bits<8, 10>(instruction)); - u32 imm8 = bits<0, 7>(instruction); + u32 opcode = Bits<11, 12>(instruction); + Register Rd = static_cast(Bits<8, 10>(instruction)); + u32 imm8 = Bits<0, 7>(instruction); switch (opcode) { case 0: // MOV Rd, #imm8 v->MOV_imm(Cond::AL, /*S=*/true, Rd, 0, imm8); @@ -125,9 +119,9 @@ static const std::array thumb_instruction_table = { { } })}, { "data processing reg", MakeMatcher("010000ooooxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<6, 9>(instruction); - Register Ra = static_cast(bits<3, 5>(instruction)); - Register Rb = static_cast(bits<0, 2>(instruction)); + u32 opcode = Bits<6, 9>(instruction); + Register Ra = static_cast(Bits<3, 5>(instruction)); + Register Rb = static_cast(Bits<0, 2>(instruction)); switch (opcode) { case 0: // AND Rd, Rm v->AND_reg(Cond::AL, /*S=*/true, Rb, Rb, 0, ShiftType::LSL, Ra); @@ -182,9 +176,9 @@ static const std::array thumb_instruction_table = { { } })}, { "special data processing", MakeMatcher("010001ooxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<8, 9>(instruction); - Register Rm = static_cast(bits<3, 6>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction) | (bits<7, 7>(instruction) << 3)); + u32 opcode = Bits<8, 9>(instruction); + Register Rm = static_cast(Bits<3, 6>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction) | (Bits<7, 7>(instruction) << 3)); switch (opcode) { case 0: // ADD Rd, Rm v->ADD_reg(Cond::AL, /*S=*/false, Rd, Rd, 0, ShiftType::LSL, Rm); @@ -200,8 +194,8 @@ static const std::array thumb_instruction_table = { { } })}, { "BLX/BX", MakeMatcher("01000111xxxxx000", [](Visitor* v, u16 instruction) { - bool L = bits<7, 7>(instruction); - Register Rm = static_cast(bits<3, 6>(instruction)); + bool L = Bits<7, 7>(instruction); + Register Rm = static_cast(Bits<3, 6>(instruction)); if (!L) { // BX Rm v->BX(Cond::AL, Rm); } else { // BLX Rm @@ -210,15 +204,15 @@ static const std::array thumb_instruction_table = { { })}, { "load from literal pool", MakeMatcher("01001xxxxxxxxxxx", [](Visitor* v, u16 instruction) { // LDR Rd, [PC, #] - Register Rd = static_cast(bits<8, 10>(instruction)); - u32 imm8 = bits<0, 7>(instruction); + Register Rd = static_cast(Bits<8, 10>(instruction)); + u32 imm8 = Bits<0, 7>(instruction); v->LDR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Register::PC, Rd, imm8 * 4); })}, { "load/store reg offset", MakeMatcher("0101oooxxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opcode = bits<9, 11>(instruction); - Register Rm = static_cast(bits<6, 8>(instruction)); - Register Rn = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opcode = Bits<9, 11>(instruction); + Register Rm = static_cast(Bits<6, 8>(instruction)); + Register Rn = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opcode) { case 0: // STR Rd, [Rn, Rm] v->STR_reg(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, 0, ShiftType::LSL, Rm); @@ -249,10 +243,10 @@ static const std::array thumb_instruction_table = { { } })}, { "STR(B)/LDR(B)_imm", MakeMatcher("011xxxxxxxxxxxxx", [](Visitor* v, u16 instruction) { - u32 opc = bits<11, 12>(instruction); - u32 offset = bits<6, 10>(instruction); - Register Rn = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opc = Bits<11, 12>(instruction); + u32 offset = Bits<6, 10>(instruction); + Register Rn = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opc) { case 0: // STR Rd, [Rn, #offset] v->STR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, offset * 4); @@ -271,10 +265,10 @@ static const std::array thumb_instruction_table = { { } })}, { "STRH/LDRH_imm", MakeMatcher("1000xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { - bool L = bits<11, 11>(instruction); - u32 offset = bits<6, 10>(instruction); - Register Rn = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + bool L = Bits<11, 11>(instruction); + u32 offset = Bits<6, 10>(instruction); + Register Rn = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); if (!L) { // STRH Rd, [Rn, #offset] v->STRH_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, (offset * 2) >> 4, (offset * 2) & 0xF); } else { // LDRH Rd, [Rn, #offset] @@ -282,9 +276,9 @@ static const std::array thumb_instruction_table = { { } })}, { "load/store stack", MakeMatcher("1001xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { - bool L = bits<11, 11>(instruction); - Register Rd = static_cast(bits<8, 10>(instruction)); - u32 offset = bits<0, 7>(instruction); + bool L = Bits<11, 11>(instruction); + Register Rd = static_cast(Bits<8, 10>(instruction)); + u32 offset = Bits<0, 7>(instruction); if (!L) { // STR Rd, [SP, #offset] v->STR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Register::SP, Rd, offset * 4); } else { // LDR Rd, [SP, #offset] @@ -293,15 +287,15 @@ static const std::array thumb_instruction_table = { { })}, { "add to sp/pc", MakeMatcher("1010oxxxxxxxxxxx", [](Visitor* v, u16 instruction) { // ADD Rd, PC/SP, #imm8 - Register Rn = bits<11, 11>(instruction) ? Register::SP : Register::PC; - Register Rd = static_cast(bits<8, 10>(instruction)); - u32 imm8 = bits<0, 7>(instruction); + Register Rn = Bits<11, 11>(instruction) ? Register::SP : Register::PC; + Register Rd = static_cast(Bits<8, 10>(instruction)); + u32 imm8 = Bits<0, 7>(instruction); v->ADD_imm(Cond::AL, /*S=*/false, Rn, Rd, 0xF, imm8); })}, { "adjust stack ptr", MakeMatcher("10110000oxxxxxxx", [](Visitor* v, u16 instruction) { // SUB SP, SP, # - u32 opc = bits<7, 7>(instruction); - u32 imm7 = bits<0, 6>(instruction); + u32 opc = Bits<7, 7>(instruction); + u32 imm7 = Bits<0, 6>(instruction); switch (opc) { case 0: v->ADD_imm(Cond::AL, /*S=*/false, Register::SP, Register::SP, 0xF, imm7); @@ -314,9 +308,9 @@ static const std::array thumb_instruction_table = { { } })}, { "sign/zero extend", MakeMatcher("10110010ooxxxxxx", [](Visitor* v, u16 instruction) { - u32 opc = bits<6, 7>(instruction); - Register Rm = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opc = Bits<6, 7>(instruction); + Register Rm = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opc) { case 0: // SXTH Rd, Rm v->SXTH(Cond::AL, Rd, SignExtendRotation::ROR_0, Rm); @@ -335,9 +329,9 @@ static const std::array thumb_instruction_table = { { } })}, { "PUSH/POP_reglist", MakeMatcher("1011x10xxxxxxxxx", [](Visitor* v, u16 instruction) { - bool L = bits<11, 11>(instruction); - u32 R = bits<8, 8>(instruction); - u32 reglist = bits<0, 7>(instruction); + bool L = Bits<11, 11>(instruction); + u32 R = Bits<8, 8>(instruction); + u32 reglist = Bits<0, 7>(instruction); if (!L) { // PUSH {reglist, =LR} reglist |= R << 14; // Equivalent to STMDB SP!, {reglist} @@ -349,20 +343,20 @@ static const std::array thumb_instruction_table = { { } })}, { "SETEND", MakeMatcher("101101100101x000", [](Visitor* v, u16 instruction) { - bool E = bits<3, 3>(instruction); + bool E = Bits<3, 3>(instruction); v->SETEND(E); })}, { "change processor state", MakeMatcher("10110110011x0xxx", [](Visitor* v, u16 instruction) { - bool imod = bits<4, 4>(instruction); - bool A = bits<2, 2>(instruction); - bool I = bits<1, 1>(instruction); - bool F = bits<0, 0>(instruction); + bool imod = Bits<4, 4>(instruction); + bool A = Bits<2, 2>(instruction); + bool I = Bits<1, 1>(instruction); + bool F = Bits<0, 0>(instruction); v->CPS(); })}, { "reverse bytes", MakeMatcher("10111010ooxxxxxx", [](Visitor* v, u16 instruction) { - u32 opc = bits<6, 7>(instruction); - Register Rn = static_cast(bits<3, 5>(instruction)); - Register Rd = static_cast(bits<0, 2>(instruction)); + u32 opc = Bits<6, 7>(instruction); + Register Rn = static_cast(Bits<3, 5>(instruction)); + Register Rd = static_cast(Bits<0, 2>(instruction)); switch (opc) { case 0: // REV Rd, Rn v->REV(Cond::AL, Rd, Rn); @@ -382,13 +376,13 @@ static const std::array thumb_instruction_table = { { })}, { "BKPT", MakeMatcher("10111110xxxxxxxx", [](Visitor* v, u16 instruction) { // BKPT #imm8 - Imm8 imm8 = bits<0, 7>(instruction); + Imm8 imm8 = Bits<0, 7>(instruction); v->BKPT(Cond::AL, imm8 >> 4, imm8 & 0xF); })}, { "STMIA/LDMIA", MakeMatcher("1100xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { - bool L = bits<11, 11>(instruction); - Register Rn = static_cast(bits<8, 10>(instruction)); - u32 reglist = bits<0, 7>(instruction); + bool L = Bits<11, 11>(instruction); + Register Rn = static_cast(Bits<8, 10>(instruction)); + u32 reglist = Bits<0, 7>(instruction); if (!L) { // STMIA Rn!, { reglist } v->STM(Cond::AL, /*P=*/0, /*U=*/1, /*W=*/1, Rn, reglist); } else { // LDMIA Rn!, { reglist } @@ -399,31 +393,31 @@ static const std::array thumb_instruction_table = { { })}, { "B", MakeMatcher("1101xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { // B - Cond cond = static_cast(bits<8, 11>(instruction)); - s32 offset = bits<0, 7>(instruction); + Cond cond = static_cast(Bits<8, 11>(instruction)); + s32 offset = Bits<0, 7>(instruction); ASSERT_MSG(cond != Cond::AL, "UNDEFINED"); v->thumb_B(cond, offset); })}, { "SWI", MakeMatcher("11011111xxxxxxxx", [](Visitor* v, u16 instruction) { // SWI #imm8 - Imm8 imm8 = bits<0, 7>(instruction); + Imm8 imm8 = Bits<0, 7>(instruction); v->SVC(Cond::AL, imm8); })}, { "B", MakeMatcher("11100xxxxxxxxxxx", [](Visitor* v, u16 instruction) { // B - Imm11 imm11 = bits<0, 10>(instruction); + Imm11 imm11 = Bits<0, 10>(instruction); v->thumb_B(imm11); })}, { "BLX (suffix)", MakeMatcher("11101xxxxxxxxxx0", [](Visitor* v, u16 instruction) { - Imm11 imm11 = bits<0, 10>(instruction); + Imm11 imm11 = Bits<0, 10>(instruction); v->thumb_BLX_suffix(/*X=*/true, imm11); })}, { "BL/BLX (prefix)", MakeMatcher("11110xxxxxxxxxxx", [](Visitor* v, u16 instruction) { - Imm11 imm11 = bits<0, 10>(instruction); + Imm11 imm11 = Bits<0, 10>(instruction); v->thumb_BLX_prefix(imm11); })}, { "BL (suffix)", MakeMatcher("11111xxxxxxxxxxx", [](Visitor* v, u16 instruction) { - Imm11 imm11 = bits<0, 10>(instruction); + Imm11 imm11 = Bits<0, 10>(instruction); v->thumb_BLX_suffix(/*X=*/false, imm11); })} }}; diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 240f55bde..40cdf34c2 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp @@ -4,8 +4,8 @@ #include #include "common/assert.h" +#include "common/bit_util.h" #include "common/common_types.h" -#include "common/math_util.h" #include "common/string_util.h" #include "core/arm/disassembler/arm_disasm.h" @@ -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 = MathUtil::SignExtend<26, s32>((imm24 << 2) + (H << 1)) + 8; + s32 offset = BitUtil::SignExtend<26, s32>((imm24 << 2) + (H << 1)) + 8; return Common::StringFromFormat("blx\t#+%d", offset); } else if ((insn & 0x0FFFFFF0) == 0x012FFF30) { u8 cond = (insn >> 28) & 0xf; diff --git a/src/core/arm/jit_x64/instructions/branch.cpp b/src/core/arm/jit_x64/instructions/branch.cpp index 32e6c2240..53516b312 100644 --- a/src/core/arm/jit_x64/instructions/branch.cpp +++ b/src/core/arm/jit_x64/instructions/branch.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/math_util.h" +#include "common/bit_util.h" #include "core/arm/jit_x64/jit_x64.h" @@ -13,7 +13,7 @@ using namespace Gen; void JitX64::B(Cond cond, ArmImm24 imm24) { cond_manager.CompileCond(cond); - const u32 new_pc = GetReg15Value() + MathUtil::SignExtend<26, s32>(imm24 << 2); + const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(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() + MathUtil::SignExtend<26, s32>(imm24 << 2); + const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(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() + MathUtil::SignExtend<26, s32>(imm24 << 2) + (H ? 2 : 0); + const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(imm24 << 2) + (H ? 2 : 0); ASSERT(!current.TFlag); const u32 link_pc = current.arm_pc + GetInstSize(); diff --git a/src/core/arm/jit_x64/instructions/thumb.cpp b/src/core/arm/jit_x64/instructions/thumb.cpp index 8b7598cd7..d82ecfb1e 100644 --- a/src/core/arm/jit_x64/instructions/thumb.cpp +++ b/src/core/arm/jit_x64/instructions/thumb.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include "common/assert.h" -#include "common/math_util.h" +#include "common/bit_util.h" #include "core/arm/jit_x64/jit_x64.h" @@ -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() + MathUtil::SignExtend<9, s32>(imm8 << 1); + const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<9, s32>(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() + MathUtil::SignExtend<12, s32>(imm11 << 1); + const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<12, s32>(imm11 << 1); reg_alloc.FlushEverything(); current.arm_pc += GetInstSize(); @@ -73,7 +73,7 @@ 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) + - MathUtil::SignExtend<23, s32>(thumb_BLX_prefix_imm11 << 12) + + BitUtil::SignExtend<23, s32>(thumb_BLX_prefix_imm11 << 12) + (imm11 << 1); u32 new_lr = (current.arm_pc + 2) | 1;