fixup! Common: Move SignExtend and bits into BitUtil

This commit is contained in:
MerryMage 2016-04-05 09:34:00 +01:00
parent ad46ecb125
commit 6ccde4718e
7 changed files with 115 additions and 100 deletions

View File

@ -26,6 +26,7 @@ set(HEADERS
assert.h assert.h
bit_field.h bit_field.h
bit_set.h bit_set.h
bit_util.h
break_points.h break_points.h
chunk_file.h chunk_file.h
code_block.h code_block.h

32
src/common/bit_util.h Normal file
View File

@ -0,0 +1,32 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#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);
}
/// Sign-extends a val of type T that has NBits bits.
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");
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;
}
} // namespace BitUtil

View File

@ -21,18 +21,6 @@ inline T Clamp(const T val, const T& min, const T& max) {
return std::max(min, std::min(max, val)); return std::max(min, std::min(max, val));
} }
/// Sign-extends a val of type T that has NBits bits.
template<size_t NBits, typename T>
inline T SignExtend(const T val) {
static_assert(std::numeric_limits<T>::is_signed, "T must be signed");
static_assert(NBits <= 8 * sizeof(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;
}
template<class T> template<class T>
struct Rectangle { struct Rectangle {
T left; T left;

View File

@ -9,6 +9,7 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/make_unique.h" #include "common/make_unique.h"
@ -42,21 +43,14 @@ ThumbMatcher MakeMatcher(const char* const str, std::function<void(Visitor* v, u
return { mask, expect, fn }; return { mask, expect, fn };
} }
template<size_t begin_bit, size_t end_bit, typename T> using BitUtil::Bits;
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);
}
static const std::array<ThumbInstruction, 27> thumb_instruction_table = { { static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
{ "LSL/LSR/ASR", MakeMatcher("000ooxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "LSL/LSR/ASR", MakeMatcher("000ooxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<11, 12>(instruction); u32 opcode = Bits<11, 12>(instruction);
u32 imm5 = bits<6, 10>(instruction); u32 imm5 = Bits<6, 10>(instruction);
Register Rm = static_cast<Register>(bits<3, 5>(instruction)); Register Rm = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opcode) { switch (opcode) {
case 0: // LSL <Rd>, <Rm>, #<imm5> case 0: // LSL <Rd>, <Rm>, #<imm5>
v->MOV_reg(Cond::AL, /*S=*/true, Rd, imm5, ShiftType::LSL, Rm); v->MOV_reg(Cond::AL, /*S=*/true, Rd, imm5, ShiftType::LSL, Rm);
@ -72,10 +66,10 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "ADD/SUB_reg", MakeMatcher("000110oxxxxxxxxx", [](Visitor* v, u16 instruction) { { "ADD/SUB_reg", MakeMatcher("000110oxxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<9, 9>(instruction); u32 opcode = Bits<9, 9>(instruction);
Register Rm = static_cast<Register>(bits<6, 8>(instruction)); Register Rm = static_cast<Register>(Bits<6, 8>(instruction));
Register Rn = static_cast<Register>(bits<3, 5>(instruction)); Register Rn = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opcode) { switch (opcode) {
case 0: // ADD <Rd>, <Rn>, <Rm> case 0: // ADD <Rd>, <Rn>, <Rm>
v->ADD_reg(Cond::AL, /*S=*/true, Rn, Rd, 0, ShiftType::LSL, Rm); v->ADD_reg(Cond::AL, /*S=*/true, Rn, Rd, 0, ShiftType::LSL, Rm);
@ -88,10 +82,10 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "ADD/SUB_imm", MakeMatcher("000111oxxxxxxxxx", [](Visitor* v, u16 instruction) { { "ADD/SUB_imm", MakeMatcher("000111oxxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<9, 9>(instruction); u32 opcode = Bits<9, 9>(instruction);
u32 imm3 = bits<6, 8>(instruction); u32 imm3 = Bits<6, 8>(instruction);
Register Rn = static_cast<Register>(bits<3, 5>(instruction)); Register Rn = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opcode) { switch (opcode) {
case 0: // ADD <Rd>, <Rn>, #<imm3> case 0: // ADD <Rd>, <Rn>, #<imm3>
v->ADD_imm(Cond::AL, /*S=*/true, Rn, Rd, 0, imm3); v->ADD_imm(Cond::AL, /*S=*/true, Rn, Rd, 0, imm3);
@ -104,9 +98,9 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "add/sub/cmp/mov_imm", MakeMatcher("001ooxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "add/sub/cmp/mov_imm", MakeMatcher("001ooxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<11, 12>(instruction); u32 opcode = Bits<11, 12>(instruction);
Register Rd = static_cast<Register>(bits<8, 10>(instruction)); Register Rd = static_cast<Register>(Bits<8, 10>(instruction));
u32 imm8 = bits<0, 7>(instruction); u32 imm8 = Bits<0, 7>(instruction);
switch (opcode) { switch (opcode) {
case 0: // MOV Rd, #imm8 case 0: // MOV Rd, #imm8
v->MOV_imm(Cond::AL, /*S=*/true, Rd, 0, imm8); v->MOV_imm(Cond::AL, /*S=*/true, Rd, 0, imm8);
@ -125,9 +119,9 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "data processing reg", MakeMatcher("010000ooooxxxxxx", [](Visitor* v, u16 instruction) { { "data processing reg", MakeMatcher("010000ooooxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<6, 9>(instruction); u32 opcode = Bits<6, 9>(instruction);
Register Ra = static_cast<Register>(bits<3, 5>(instruction)); Register Ra = static_cast<Register>(Bits<3, 5>(instruction));
Register Rb = static_cast<Register>(bits<0, 2>(instruction)); Register Rb = static_cast<Register>(Bits<0, 2>(instruction));
switch (opcode) { switch (opcode) {
case 0: // AND Rd, Rm case 0: // AND Rd, Rm
v->AND_reg(Cond::AL, /*S=*/true, Rb, Rb, 0, ShiftType::LSL, Ra); v->AND_reg(Cond::AL, /*S=*/true, Rb, Rb, 0, ShiftType::LSL, Ra);
@ -182,9 +176,9 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "special data processing", MakeMatcher("010001ooxxxxxxxx", [](Visitor* v, u16 instruction) { { "special data processing", MakeMatcher("010001ooxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<8, 9>(instruction); u32 opcode = Bits<8, 9>(instruction);
Register Rm = static_cast<Register>(bits<3, 6>(instruction)); Register Rm = static_cast<Register>(Bits<3, 6>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction) | (bits<7, 7>(instruction) << 3)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction) | (Bits<7, 7>(instruction) << 3));
switch (opcode) { switch (opcode) {
case 0: // ADD Rd, Rm case 0: // ADD Rd, Rm
v->ADD_reg(Cond::AL, /*S=*/false, Rd, Rd, 0, ShiftType::LSL, Rm); v->ADD_reg(Cond::AL, /*S=*/false, Rd, Rd, 0, ShiftType::LSL, Rm);
@ -200,8 +194,8 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "BLX/BX", MakeMatcher("01000111xxxxx000", [](Visitor* v, u16 instruction) { { "BLX/BX", MakeMatcher("01000111xxxxx000", [](Visitor* v, u16 instruction) {
bool L = bits<7, 7>(instruction); bool L = Bits<7, 7>(instruction);
Register Rm = static_cast<Register>(bits<3, 6>(instruction)); Register Rm = static_cast<Register>(Bits<3, 6>(instruction));
if (!L) { // BX Rm if (!L) { // BX Rm
v->BX(Cond::AL, Rm); v->BX(Cond::AL, Rm);
} else { // BLX Rm } else { // BLX Rm
@ -210,15 +204,15 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
})}, })},
{ "load from literal pool", MakeMatcher("01001xxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "load from literal pool", MakeMatcher("01001xxxxxxxxxxx", [](Visitor* v, u16 instruction) {
// LDR Rd, [PC, #] // LDR Rd, [PC, #]
Register Rd = static_cast<Register>(bits<8, 10>(instruction)); Register Rd = static_cast<Register>(Bits<8, 10>(instruction));
u32 imm8 = bits<0, 7>(instruction); u32 imm8 = Bits<0, 7>(instruction);
v->LDR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Register::PC, Rd, imm8 * 4); 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) { { "load/store reg offset", MakeMatcher("0101oooxxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opcode = bits<9, 11>(instruction); u32 opcode = Bits<9, 11>(instruction);
Register Rm = static_cast<Register>(bits<6, 8>(instruction)); Register Rm = static_cast<Register>(Bits<6, 8>(instruction));
Register Rn = static_cast<Register>(bits<3, 5>(instruction)); Register Rn = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opcode) { switch (opcode) {
case 0: // STR Rd, [Rn, Rm] case 0: // STR Rd, [Rn, Rm]
v->STR_reg(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, 0, ShiftType::LSL, 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<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "STR(B)/LDR(B)_imm", MakeMatcher("011xxxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "STR(B)/LDR(B)_imm", MakeMatcher("011xxxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
u32 opc = bits<11, 12>(instruction); u32 opc = Bits<11, 12>(instruction);
u32 offset = bits<6, 10>(instruction); u32 offset = Bits<6, 10>(instruction);
Register Rn = static_cast<Register>(bits<3, 5>(instruction)); Register Rn = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opc) { switch (opc) {
case 0: // STR Rd, [Rn, #offset] case 0: // STR Rd, [Rn, #offset]
v->STR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, offset * 4); v->STR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, offset * 4);
@ -271,10 +265,10 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "STRH/LDRH_imm", MakeMatcher("1000xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "STRH/LDRH_imm", MakeMatcher("1000xxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
bool L = bits<11, 11>(instruction); bool L = Bits<11, 11>(instruction);
u32 offset = bits<6, 10>(instruction); u32 offset = Bits<6, 10>(instruction);
Register Rn = static_cast<Register>(bits<3, 5>(instruction)); Register Rn = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
if (!L) { // STRH Rd, [Rn, #offset] 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); v->STRH_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Rn, Rd, (offset * 2) >> 4, (offset * 2) & 0xF);
} else { // LDRH Rd, [Rn, #offset] } else { // LDRH Rd, [Rn, #offset]
@ -282,9 +276,9 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "load/store stack", MakeMatcher("1001xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "load/store stack", MakeMatcher("1001xxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
bool L = bits<11, 11>(instruction); bool L = Bits<11, 11>(instruction);
Register Rd = static_cast<Register>(bits<8, 10>(instruction)); Register Rd = static_cast<Register>(Bits<8, 10>(instruction));
u32 offset = bits<0, 7>(instruction); u32 offset = Bits<0, 7>(instruction);
if (!L) { // STR Rd, [SP, #offset] if (!L) { // STR Rd, [SP, #offset]
v->STR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Register::SP, Rd, offset * 4); v->STR_imm(Cond::AL, /*P=*/1, /*U=*/1, /*W=*/0, Register::SP, Rd, offset * 4);
} else { // LDR Rd, [SP, #offset] } else { // LDR Rd, [SP, #offset]
@ -293,15 +287,15 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
})}, })},
{ "add to sp/pc", MakeMatcher("1010oxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "add to sp/pc", MakeMatcher("1010oxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
// ADD Rd, PC/SP, #imm8 // ADD Rd, PC/SP, #imm8
Register Rn = bits<11, 11>(instruction) ? Register::SP : Register::PC; Register Rn = Bits<11, 11>(instruction) ? Register::SP : Register::PC;
Register Rd = static_cast<Register>(bits<8, 10>(instruction)); Register Rd = static_cast<Register>(Bits<8, 10>(instruction));
u32 imm8 = bits<0, 7>(instruction); u32 imm8 = Bits<0, 7>(instruction);
v->ADD_imm(Cond::AL, /*S=*/false, Rn, Rd, 0xF, imm8); v->ADD_imm(Cond::AL, /*S=*/false, Rn, Rd, 0xF, imm8);
})}, })},
{ "adjust stack ptr", MakeMatcher("10110000oxxxxxxx", [](Visitor* v, u16 instruction) { { "adjust stack ptr", MakeMatcher("10110000oxxxxxxx", [](Visitor* v, u16 instruction) {
// SUB SP, SP, #<imm7*4> // SUB SP, SP, #<imm7*4>
u32 opc = bits<7, 7>(instruction); u32 opc = Bits<7, 7>(instruction);
u32 imm7 = bits<0, 6>(instruction); u32 imm7 = Bits<0, 6>(instruction);
switch (opc) { switch (opc) {
case 0: case 0:
v->ADD_imm(Cond::AL, /*S=*/false, Register::SP, Register::SP, 0xF, imm7); v->ADD_imm(Cond::AL, /*S=*/false, Register::SP, Register::SP, 0xF, imm7);
@ -314,9 +308,9 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "sign/zero extend", MakeMatcher("10110010ooxxxxxx", [](Visitor* v, u16 instruction) { { "sign/zero extend", MakeMatcher("10110010ooxxxxxx", [](Visitor* v, u16 instruction) {
u32 opc = bits<6, 7>(instruction); u32 opc = Bits<6, 7>(instruction);
Register Rm = static_cast<Register>(bits<3, 5>(instruction)); Register Rm = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opc) { switch (opc) {
case 0: // SXTH Rd, Rm case 0: // SXTH Rd, Rm
v->SXTH(Cond::AL, Rd, SignExtendRotation::ROR_0, Rm); v->SXTH(Cond::AL, Rd, SignExtendRotation::ROR_0, Rm);
@ -335,9 +329,9 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "PUSH/POP_reglist", MakeMatcher("1011x10xxxxxxxxx", [](Visitor* v, u16 instruction) { { "PUSH/POP_reglist", MakeMatcher("1011x10xxxxxxxxx", [](Visitor* v, u16 instruction) {
bool L = bits<11, 11>(instruction); bool L = Bits<11, 11>(instruction);
u32 R = bits<8, 8>(instruction); u32 R = Bits<8, 8>(instruction);
u32 reglist = bits<0, 7>(instruction); u32 reglist = Bits<0, 7>(instruction);
if (!L) { // PUSH {reglist, <R>=LR} if (!L) { // PUSH {reglist, <R>=LR}
reglist |= R << 14; reglist |= R << 14;
// Equivalent to STMDB SP!, {reglist} // Equivalent to STMDB SP!, {reglist}
@ -349,20 +343,20 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
} }
})}, })},
{ "SETEND", MakeMatcher("101101100101x000", [](Visitor* v, u16 instruction) { { "SETEND", MakeMatcher("101101100101x000", [](Visitor* v, u16 instruction) {
bool E = bits<3, 3>(instruction); bool E = Bits<3, 3>(instruction);
v->SETEND(E); v->SETEND(E);
})}, })},
{ "change processor state", MakeMatcher("10110110011x0xxx", [](Visitor* v, u16 instruction) { { "change processor state", MakeMatcher("10110110011x0xxx", [](Visitor* v, u16 instruction) {
bool imod = bits<4, 4>(instruction); bool imod = Bits<4, 4>(instruction);
bool A = bits<2, 2>(instruction); bool A = Bits<2, 2>(instruction);
bool I = bits<1, 1>(instruction); bool I = Bits<1, 1>(instruction);
bool F = bits<0, 0>(instruction); bool F = Bits<0, 0>(instruction);
v->CPS(); v->CPS();
})}, })},
{ "reverse bytes", MakeMatcher("10111010ooxxxxxx", [](Visitor* v, u16 instruction) { { "reverse bytes", MakeMatcher("10111010ooxxxxxx", [](Visitor* v, u16 instruction) {
u32 opc = bits<6, 7>(instruction); u32 opc = Bits<6, 7>(instruction);
Register Rn = static_cast<Register>(bits<3, 5>(instruction)); Register Rn = static_cast<Register>(Bits<3, 5>(instruction));
Register Rd = static_cast<Register>(bits<0, 2>(instruction)); Register Rd = static_cast<Register>(Bits<0, 2>(instruction));
switch (opc) { switch (opc) {
case 0: // REV Rd, Rn case 0: // REV Rd, Rn
v->REV(Cond::AL, Rd, Rn); v->REV(Cond::AL, Rd, Rn);
@ -382,13 +376,13 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
})}, })},
{ "BKPT", MakeMatcher("10111110xxxxxxxx", [](Visitor* v, u16 instruction) { { "BKPT", MakeMatcher("10111110xxxxxxxx", [](Visitor* v, u16 instruction) {
// BKPT #imm8 // BKPT #imm8
Imm8 imm8 = bits<0, 7>(instruction); Imm8 imm8 = Bits<0, 7>(instruction);
v->BKPT(Cond::AL, imm8 >> 4, imm8 & 0xF); v->BKPT(Cond::AL, imm8 >> 4, imm8 & 0xF);
})}, })},
{ "STMIA/LDMIA", MakeMatcher("1100xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "STMIA/LDMIA", MakeMatcher("1100xxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
bool L = bits<11, 11>(instruction); bool L = Bits<11, 11>(instruction);
Register Rn = static_cast<Register>(bits<8, 10>(instruction)); Register Rn = static_cast<Register>(Bits<8, 10>(instruction));
u32 reglist = bits<0, 7>(instruction); u32 reglist = Bits<0, 7>(instruction);
if (!L) { // STMIA Rn!, { reglist } if (!L) { // STMIA Rn!, { reglist }
v->STM(Cond::AL, /*P=*/0, /*U=*/1, /*W=*/1, Rn, reglist); v->STM(Cond::AL, /*P=*/0, /*U=*/1, /*W=*/1, Rn, reglist);
} else { // LDMIA Rn!, { reglist } } else { // LDMIA Rn!, { reglist }
@ -399,31 +393,31 @@ static const std::array<ThumbInstruction, 27> thumb_instruction_table = { {
})}, })},
{ "B<cond>", MakeMatcher("1101xxxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "B<cond>", MakeMatcher("1101xxxxxxxxxxxx", [](Visitor* v, u16 instruction) {
// B<cond> <PC + #offset*2> // B<cond> <PC + #offset*2>
Cond cond = static_cast<Cond>(bits<8, 11>(instruction)); Cond cond = static_cast<Cond>(Bits<8, 11>(instruction));
s32 offset = bits<0, 7>(instruction); s32 offset = Bits<0, 7>(instruction);
ASSERT_MSG(cond != Cond::AL, "UNDEFINED"); ASSERT_MSG(cond != Cond::AL, "UNDEFINED");
v->thumb_B(cond, offset); v->thumb_B(cond, offset);
})}, })},
{ "SWI", MakeMatcher("11011111xxxxxxxx", [](Visitor* v, u16 instruction) { { "SWI", MakeMatcher("11011111xxxxxxxx", [](Visitor* v, u16 instruction) {
// SWI #imm8 // SWI #imm8
Imm8 imm8 = bits<0, 7>(instruction); Imm8 imm8 = Bits<0, 7>(instruction);
v->SVC(Cond::AL, imm8); v->SVC(Cond::AL, imm8);
})}, })},
{ "B", MakeMatcher("11100xxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "B", MakeMatcher("11100xxxxxxxxxxx", [](Visitor* v, u16 instruction) {
// B <PC + #offset*2> // B <PC + #offset*2>
Imm11 imm11 = bits<0, 10>(instruction); Imm11 imm11 = Bits<0, 10>(instruction);
v->thumb_B(imm11); v->thumb_B(imm11);
})}, })},
{ "BLX (suffix)", MakeMatcher("11101xxxxxxxxxx0", [](Visitor* v, u16 instruction) { { "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); v->thumb_BLX_suffix(/*X=*/true, imm11);
})}, })},
{ "BL/BLX (prefix)", MakeMatcher("11110xxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "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); v->thumb_BLX_prefix(imm11);
})}, })},
{ "BL (suffix)", MakeMatcher("11111xxxxxxxxxxx", [](Visitor* v, u16 instruction) { { "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); v->thumb_BLX_suffix(/*X=*/false, imm11);
})} })}
}}; }};

View File

@ -4,8 +4,8 @@
#include <unordered_set> #include <unordered_set>
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/math_util.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/arm/disassembler/arm_disasm.h" #include "core/arm/disassembler/arm_disasm.h"
@ -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 = 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); 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

@ -2,7 +2,7 @@
// 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 "common/math_util.h" #include "common/bit_util.h"
#include "core/arm/jit_x64/jit_x64.h" #include "core/arm/jit_x64/jit_x64.h"
@ -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() + MathUtil::SignExtend<26, s32>(imm24 << 2); const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(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() + MathUtil::SignExtend<26, s32>(imm24 << 2); const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<26, s32>(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() + 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); ASSERT(!current.TFlag);
const u32 link_pc = current.arm_pc + GetInstSize(); const u32 link_pc = current.arm_pc + GetInstSize();

View File

@ -3,7 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/assert.h" #include "common/assert.h"
#include "common/math_util.h" #include "common/bit_util.h"
#include "core/arm/jit_x64/jit_x64.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"); 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(); 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() + MathUtil::SignExtend<12, s32>(imm11 << 1); const u32 new_pc = GetReg15Value() + BitUtil::SignExtend<12, s32>(imm11 << 1);
reg_alloc.FlushEverything(); reg_alloc.FlushEverything();
current.arm_pc += GetInstSize(); 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); 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) +
MathUtil::SignExtend<23, s32>(thumb_BLX_prefix_imm11 << 12) + BitUtil::SignExtend<23, s32>(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;