Merge pull request #489 from lioncash/imm

A32: Replace immediate type aliases with the Imm template
This commit is contained in:
Merry 2019-05-01 16:02:44 +01:00 committed by MerryMage
commit dd79a3dc6b
17 changed files with 765 additions and 541 deletions

View file

@ -12,6 +12,7 @@
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "frontend/imm.h"
#include "frontend/A32/decoder/arm.h" #include "frontend/A32/decoder/arm.h"
#include "frontend/A32/decoder/vfp2.h" #include "frontend/A32/decoder/vfp2.h"
#include "frontend/A32/disassembler/disassembler.h" #include "frontend/A32/disassembler/disassembler.h"
@ -23,24 +24,24 @@ class DisassemblerVisitor {
public: public:
using instruction_return_type = std::string; using instruction_return_type = std::string;
static u32 ArmExpandImm(int rotate, Imm8 imm8) { static u32 ArmExpandImm(int rotate, Imm<8> imm8) {
return Common::RotateRight(static_cast<u32>(imm8), rotate*2); return Common::RotateRight(static_cast<u32>(imm8.ZeroExtend()), rotate*2);
} }
static std::string ShiftStr(ShiftType shift, Imm5 imm5) { static std::string ShiftStr(ShiftType shift, Imm<5> imm5) {
switch (shift) { switch (shift) {
case ShiftType::LSL: case ShiftType::LSL:
if (imm5 == 0) return ""; if (imm5 == 0) return "";
return fmt::format(", lsl #{}", imm5); return fmt::format(", lsl #{}", imm5.ZeroExtend());
case ShiftType::LSR: case ShiftType::LSR:
if (imm5 == 0) return ", lsr #32"; if (imm5 == 0) return ", lsr #32";
return fmt::format(", lsr #{}", imm5); return fmt::format(", lsr #{}", imm5.ZeroExtend());
case ShiftType::ASR: case ShiftType::ASR:
if (imm5 == 0) return ", asr #32"; if (imm5 == 0) return ", asr #32";
return fmt::format(", asr #{}", imm5); return fmt::format(", asr #{}", imm5.ZeroExtend());
case ShiftType::ROR: case ShiftType::ROR:
if (imm5 == 0) return ", rrx"; if (imm5 == 0) return ", rrx";
return fmt::format(", ror #{}", imm5); return fmt::format(", ror #{}", imm5.ZeroExtend());
} }
ASSERT(false); ASSERT(false);
return "<internal error>"; return "<internal error>";
@ -76,8 +77,8 @@ public:
return "<internal error>"; return "<internal error>";
} }
static const char* BarrierOptionStr(Imm4 option) { static const char* BarrierOptionStr(Imm<4> option) {
switch (option) { switch (option.ZeroExtend()) {
case 0b0010: case 0b0010:
return " oshst"; return " oshst";
case 0b0011: case 0b0011:
@ -124,27 +125,27 @@ public:
} }
// Barrier instructions // Barrier instructions
std::string arm_DMB(Imm4 option) { std::string arm_DMB(Imm<4> option) {
return fmt::format("dmb{}", BarrierOptionStr(option)); return fmt::format("dmb{}", BarrierOptionStr(option));
} }
std::string arm_DSB(Imm4 option) { std::string arm_DSB(Imm<4> option) {
return fmt::format("dsb{}", BarrierOptionStr(option)); return fmt::format("dsb{}", BarrierOptionStr(option));
} }
std::string arm_ISB([[maybe_unused]] Imm4 option) { std::string arm_ISB([[maybe_unused]] Imm<4> option) {
return "isb"; return "isb";
} }
// Branch instructions // Branch instructions
std::string arm_B(Cond cond, Imm24 imm24) { std::string arm_B(Cond cond, Imm<24> imm24) {
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8; const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8;
return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset)); return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
} }
std::string arm_BL(Cond cond, Imm24 imm24) { std::string arm_BL(Cond cond, Imm<24> imm24) {
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8; const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8;
return fmt::format("bl{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset)); return fmt::format("bl{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
} }
std::string arm_BLX_imm(bool H, Imm24 imm24) { std::string arm_BLX_imm(bool H, Imm<24> imm24) {
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8 + (H ? 2 : 0); const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8 + (H ? 2 : 0);
return fmt::format("blx {}#{}", Common::SignToChar(offset), abs(offset)); return fmt::format("blx {}#{}", Common::SignToChar(offset), abs(offset));
} }
std::string arm_BLX_reg(Cond cond, Reg m) { std::string arm_BLX_reg(Cond cond, Reg m) {
@ -162,16 +163,24 @@ public:
return fmt::format("cdp{} p{}, #{}, {}, {}, {}, #{}", CondToString(cond), coproc_no, opc1, CRd, CRn, CRm, opc2); return fmt::format("cdp{} p{}, #{}, {}, {}, {}, #{}", CondToString(cond), coproc_no, opc1, CRd, CRn, CRm, opc2);
} }
std::string arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) { std::string arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
const u32 imm32 = static_cast<u32>(imm8) << 2; const u32 imm32 = static_cast<u32>(imm8.ZeroExtend()) << 2;
if (!p && !u && !d && !w) if (!p && !u && !d && !w) {
return "<undefined>"; return "<undefined>";
if (p) }
return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : ""); if (p) {
if (!p && w) return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "",
return fmt::format("ldc{}{} {}, {}, [{}], #{}{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32); CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32,
if (!p && !w && u) w ? "!" : "");
return fmt::format("ldc{}{} {}, {}, [{}], {}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, imm8); }
if (!p && w) {
return fmt::format("ldc{}{} {}, {}, [{}], #{}{}", d ? "l" : "",
CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32);
}
if (!p && !w && u) {
return fmt::format("ldc{}{} {}, {}, [{}], {}", d ? "l" : "",
CondOrTwo(cond), coproc_no, CRd, n, imm8.ZeroExtend());
}
UNREACHABLE(); UNREACHABLE();
return "<internal error>"; return "<internal error>";
} }
@ -192,160 +201,169 @@ public:
return fmt::format("mrrc{} p{}, #{}, {}, {}, {}", CondOrTwo(cond), coproc_no, opc, t, t2, CRm); return fmt::format("mrrc{} p{}, #{}, {}, {}, {}", CondOrTwo(cond), coproc_no, opc, t, t2, CRm);
} }
std::string arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) { std::string arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
const u32 imm32 = static_cast<u32>(imm8) << 2; const u32 imm32 = static_cast<u32>(imm8.ZeroExtend()) << 2;
if (!p && !u && !d && !w) if (!p && !u && !d && !w) {
return "<undefined>"; return "<undefined>";
if (p) }
return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : ""); if (p) {
if (!p && w) return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "",
return fmt::format("stc{}{} {}, {}, [{}], #{}{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32); CondOrTwo(cond), coproc_no, CRd, n,
if (!p && !w && u) u ? "+" : "-", imm32, w ? "!" : "");
return fmt::format("stc{}{} {}, {}, [{}], {}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, imm8); }
if (!p && w) {
return fmt::format("stc{}{} {}, {}, [{}], #{}{}", d ? "l" : "",
CondOrTwo(cond), coproc_no, CRd, n,
u ? "+" : "-", imm32);
}
if (!p && !w && u) {
return fmt::format("stc{}{} {}, {}, [{}], {}", d ? "l" : "",
CondOrTwo(cond), coproc_no, CRd, n, imm8.ZeroExtend());
}
UNREACHABLE(); UNREACHABLE();
return "<internal error>"; return "<internal error>";
} }
// Data processing instructions // Data processing instructions
std::string arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("adc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("adc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("adc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("adc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("adc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("adc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("add{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("add{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("add{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("add{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("add{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("add{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("and{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("and{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("and{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("and{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("and{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("and{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("bic{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("bic{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("bic{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("bic{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("bic{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("bic{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { std::string arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
return fmt::format("cmn{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8)); return fmt::format("cmn{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
} }
std::string arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("cmn{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5)); return fmt::format("cmn{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
} }
std::string arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { std::string arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
return fmt::format("cmn{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m)); return fmt::format("cmn{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
} }
std::string arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { std::string arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
return fmt::format("cmp{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8)); return fmt::format("cmp{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
} }
std::string arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("cmp{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5)); return fmt::format("cmp{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
} }
std::string arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { std::string arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
return fmt::format("cmp{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m)); return fmt::format("cmp{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
} }
std::string arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("eor{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("eor{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("eor{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("eor{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("eor{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("eor{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { std::string arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("mov{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8)); return fmt::format("mov{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8));
} }
std::string arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("mov{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5)); return fmt::format("mov{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5));
} }
std::string arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("mov{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m)); return fmt::format("mov{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m));
} }
std::string arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { std::string arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("mvn{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8)); return fmt::format("mvn{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8));
} }
std::string arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("mvn{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5)); return fmt::format("mvn{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5));
} }
std::string arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("mvn{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m)); return fmt::format("mvn{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m));
} }
std::string arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("orr{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("orr{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("orr{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("orr{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("orr{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("orr{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("rsb{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("rsb{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("rsb{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("rsb{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("rsb{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("rsb{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("rsc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("rsc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("rsc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("rsc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("rsc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("rsc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("sbc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("sbc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("sbc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("sbc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("sbc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("sbc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { std::string arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
return fmt::format("sub{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8)); return fmt::format("sub{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
} }
std::string arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("sub{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5)); return fmt::format("sub{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
} }
std::string arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { std::string arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
return fmt::format("sub{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m)); return fmt::format("sub{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
} }
std::string arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { std::string arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
return fmt::format("teq{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8)); return fmt::format("teq{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
} }
std::string arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("teq{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5)); return fmt::format("teq{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
} }
std::string arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { std::string arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
return fmt::format("teq{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m)); return fmt::format("teq{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
} }
std::string arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { std::string arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
return fmt::format("tst{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8)); return fmt::format("tst{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
} }
std::string arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
return fmt::format("tst{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5)); return fmt::format("tst{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
} }
std::string arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { std::string arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
@ -353,11 +371,11 @@ public:
} }
// Exception generation instructions // Exception generation instructions
std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) { std::string arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4) {
return fmt::format("bkpt{} #{}", CondToString(cond), imm12 << 4 | imm4); return fmt::format("bkpt{} #{}", CondToString(cond), concatenate(imm12, imm4).ZeroExtend());
} }
std::string arm_SVC(Cond cond, Imm24 imm24) { std::string arm_SVC(Cond cond, Imm<24> imm24) {
return fmt::format("svc{} #{}", CondToString(cond), imm24); return fmt::format("svc{} #{}", CondToString(cond), imm24.ZeroExtend());
} }
std::string arm_UDF() { std::string arm_UDF() {
return fmt::format("udf"); return fmt::format("udf");
@ -409,179 +427,307 @@ public:
std::string arm_YIELD() { return "yield <unimplemented>"; } std::string arm_YIELD() { return "yield <unimplemented>"; }
// Load/Store instructions // Load/Store instructions
std::string arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) { std::string arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
bool P = true, W = false; bool P = true, W = false;
return arm_LDR_imm(cond, P, U, W, Reg::PC, t, imm12); return arm_LDR_imm(cond, P, U, W, Reg::PC, t, imm12);
} }
std::string arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { std::string arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
const u32 imm12_value = imm12.ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldr{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : ""); return fmt::format("ldr{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign,
imm12_value, W ? "!" : "");
} else { } else {
return fmt::format("ldr{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldr{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign,
imm12_value, W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldr{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : ""); return fmt::format("ldr{} {}, [{}, {}{}{}]{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? "!" : "");
} else { } else {
return fmt::format("ldr{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : ""); return fmt::format("ldr{} {}, [{}], {}{}{}{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) { std::string arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
bool P = true, W = false; const bool P = true;
const bool W = false;
return arm_LDRB_imm(cond, P, U, W, Reg::PC, t, imm12); return arm_LDRB_imm(cond, P, U, W, Reg::PC, t, imm12);
} }
std::string arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { std::string arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
const u32 imm12_value = imm12.ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : ""); return fmt::format("ldrb{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm12_value,
W ? "!" : "");
} else { } else {
return fmt::format("ldrb{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrb{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm12_value,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrb{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : ""); return fmt::format("ldrb{} {}, [{}, {}{}{}]{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? "!" : "");
} else { } else {
return fmt::format("ldrb{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrb{} {}, [{}], {}{}{}{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRBT() { return "ice"; } std::string arm_LDRBT() { return "ice"; }
std::string arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
bool P = true, W = false; const bool P = true;
const bool W = false;
return arm_LDRD_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b); return arm_LDRD_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
} }
std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrd{} {}, {}, [{}, #{}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? "!" : ""); return fmt::format("ldrd{} {}, {}, [{}, #{}{}]{}",
CondToString(cond), t, t+1, n, sign, imm32,
W ? "!" : "");
} else { } else {
return fmt::format("ldrd{} {}, {}, [{}], #{}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrd{} {}, {}, [{}], #{}{}{}",
CondToString(cond), t, t+1, n, sign, imm32,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { std::string arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrd{} {}, {}, [{}, {}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? "!" : ""); return fmt::format("ldrd{} {}, {}, [{}, {}{}]{}",
CondToString(cond), t, t+1, n, sign, m,
W ? "!" : "");
} else { } else {
return fmt::format("ldrd{} {}, {}, [{}], {}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrd{} {}, {}, [{}], {}{}{}",
CondToString(cond), t, t+1, n, sign, m,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
return arm_LDRH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b); return arm_LDRH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
} }
std::string arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrh{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : ""); return fmt::format("ldrh{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm32,
W ? "!" : "");
} else { } else {
return fmt::format("ldrh{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrh{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm32,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { std::string arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrh{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : ""); return fmt::format("ldrh{} {}, [{}, {}{}]{}",
CondToString(cond), t, n, sign, m,
W ? "!" : "");
} else { } else {
return fmt::format("ldrh{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrh{} {}, [{}], {}{}{}",
CondToString(cond), t, n, sign, m,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRHT() { return "ice"; } std::string arm_LDRHT() { return "ice"; }
std::string arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
bool P = true, W = false; const bool P = true;
const bool W = false;
return arm_LDRSB_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b); return arm_LDRSB_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
} }
std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrsb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : ""); return fmt::format("ldrsb{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm32,
W ? "!" : "");
} else { } else {
return fmt::format("ldrsb{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrsb{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm32,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { std::string arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrsb{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : ""); return fmt::format("ldrsb{} {}, [{}, {}{}]{}",
CondToString(cond), t, n, sign, m,
W ? "!" : "");
} else { } else {
return fmt::format("ldrsb{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrsb{} {}, [{}], {}{}{}",
CondToString(cond), t, n, sign, m,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRSBT() { return "ice"; } std::string arm_LDRSBT() { return "ice"; }
std::string arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
bool P = true, W = false; const bool P = true;
const bool W = false;
return arm_LDRSH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b); return arm_LDRSH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
} }
std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrsh{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : ""); return fmt::format("ldrsh{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm32,
W ? "!" : "");
} else { } else {
return fmt::format("ldrsh{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrsh{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm32,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { std::string arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("ldrsh{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : ""); return fmt::format("ldrsh{} {}, [{}, {}{}]{}",
CondToString(cond), t, n, sign, m,
W ? "!" : "");
} else { } else {
return fmt::format("ldrsh{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : ""); return fmt::format("ldrsh{} {}, [{}], {}{}{}",
CondToString(cond), t, n, sign, m,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_LDRSHT() { return "ice"; } std::string arm_LDRSHT() { return "ice"; }
std::string arm_LDRT() { return "ice"; } std::string arm_LDRT() { return "ice"; }
std::string arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { std::string arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
const u32 imm12_value = imm12.ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("str{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : ""); return fmt::format("str{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm12_value,
W ? "!" : "");
} else { } else {
return fmt::format("str{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : ""); return fmt::format("str{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm12_value,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("str{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : ""); return fmt::format("str{} {}, [{}, {}{}{}]{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? "!" : "");
} else { } else {
return fmt::format("str{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : ""); return fmt::format("str{} {}, [{}], {}{}{}{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { std::string arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
const u32 imm12_value = imm12.ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("strb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : ""); return fmt::format("strb{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm12_value,
W ? "!" : "");
} else { } else {
return fmt::format("strb{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : ""); return fmt::format("strb{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm12_value,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { std::string arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("strb{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : ""); return fmt::format("strb{} {}, [{}, {}{}{}]{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? "!" : "");
} else { } else {
return fmt::format("strb{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : ""); return fmt::format("strb{} {}, [{}], {}{}{}{}",
CondToString(cond), t, n, sign, m,
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRBT() { return "ice"; } std::string arm_STRBT() { return "ice"; }
std::string arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("strd{} {}, {}, [{}, #{}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? "!" : ""); return fmt::format("strd{} {}, {}, [{}, #{}{}]{}",
CondToString(cond), t, t+1, n, sign, imm32,
W ? "!" : "");
} else { } else {
return fmt::format("strd{} {}, {}, [{}], #{}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : ""); return fmt::format("strd{} {}, {}, [{}], #{}{}{}",
CondToString(cond), t, t+1, n, sign, imm32,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { std::string arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("strd{} {}, {}, [{}, {}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? "!" : ""); return fmt::format("strd{} {}, {}, [{}, {}{}]{}",
CondToString(cond), t, t+1, n, sign, m,
W ? "!" : "");
} else { } else {
return fmt::format("strd{} {}, {}, [{}], {}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : ""); return fmt::format("strd{} {}, {}, [{}], {}{}{}",
CondToString(cond), t, t+1, n, sign, m,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { std::string arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("strh{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : ""); return fmt::format("strh{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm32,
W ? "!" : "");
} else { } else {
return fmt::format("strh{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : ""); return fmt::format("strh{} {}, [{}], #{}{}{}",
CondToString(cond), t, n, sign, imm32,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { std::string arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
const char sign = U ? '+' : '-';
if (P) { if (P) {
return fmt::format("strd{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : ""); return fmt::format("strd{} {}, [{}, {}{}]{}",
CondToString(cond), t, n, sign, m,
W ? "!" : "");
} else { } else {
return fmt::format("strd{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : ""); return fmt::format("strd{} {}, [{}], {}{}{}",
CondToString(cond), t, n, sign, m,
W ? " (err: W == 1!!!)" : "");
} }
} }
std::string arm_STRHT() { return "ice"; } std::string arm_STRHT() { return "ice"; }
@ -617,17 +763,24 @@ public:
std::string arm_STM_usr() { return "ice"; } std::string arm_STM_usr() { return "ice"; }
// Miscellaneous instructions // Miscellaneous instructions
std::string arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) { std::string arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb) {
return fmt::format("bfc{} {}, #{}, #{}", CondToString(cond), d, lsb, msb - lsb + 1); const u32 lsb_value = lsb.ZeroExtend();
const u32 width = msb.ZeroExtend() - lsb_value + 1;
return fmt::format("bfc{} {}, #{}, #{}",
CondToString(cond), d, lsb_value, width);
} }
std::string arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n) { std::string arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n) {
return fmt::format("bfi{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, msb - lsb + 1); const u32 lsb_value = lsb.ZeroExtend();
const u32 width = msb.ZeroExtend() - lsb_value + 1;
return fmt::format("bfi{} {}, {}, #{}, #{}",
CondToString(cond), d, n, lsb_value, width);
} }
std::string arm_CLZ(Cond cond, Reg d, Reg m) { std::string arm_CLZ(Cond cond, Reg d, Reg m) {
return fmt::format("clz{} {}, {}", CondToString(cond), d, m); return fmt::format("clz{} {}, {}", CondToString(cond), d, m);
} }
std::string arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) { std::string arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12) {
return fmt::format("movt{} {}, #{}", CondToString(cond), d, (imm4 << 12) | imm12); const u32 imm = concatenate(imm4, imm12).ZeroExtend();
return fmt::format("movt{} {}, #{}", CondToString(cond), d, imm);
} }
std::string arm_NOP() { std::string arm_NOP() {
return "nop"; return "nop";
@ -635,14 +788,20 @@ public:
std::string arm_RBIT(Cond cond, Reg d, Reg m) { std::string arm_RBIT(Cond cond, Reg d, Reg m) {
return fmt::format("rbit{} {}, {}", CondToString(cond), d, m); return fmt::format("rbit{} {}, {}", CondToString(cond), d, m);
} }
std::string arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) { std::string arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
return fmt::format("sbfx{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, widthm1 + 1); const u32 lsb_value = lsb.ZeroExtend();
const u32 width = widthm1.ZeroExtend() + 1;
return fmt::format("sbfx{} {}, {}, #{}, #{}",
CondToString(cond), d, n, lsb_value, width);
} }
std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) { std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) {
return fmt::format("sel{} {}, {}, {}", CondToString(cond), d, n, m); return fmt::format("sel{} {}, {}, {}", CondToString(cond), d, n, m);
} }
std::string arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) { std::string arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
return fmt::format("ubfx{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, widthm1 + 1); const u32 lsb_value = lsb.ZeroExtend();
const u32 width = widthm1.ZeroExtend() + 1;
return fmt::format("ubfx{} {}, {}, #{}, #{}",
CondToString(cond), d, n, lsb_value, width);
} }
// Unsigned sum of absolute difference functions // Unsigned sum of absolute difference functions
@ -654,10 +813,10 @@ public:
} }
// Packing instructions // Packing instructions
std::string arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) { std::string arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
return fmt::format("pkhbt{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::LSL, imm5)); return fmt::format("pkhbt{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::LSL, imm5));
} }
std::string arm_PKHTB(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) { std::string arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
return fmt::format("pkhtb{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::ASR, imm5)); return fmt::format("pkhtb{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::ASR, imm5));
} }
@ -673,17 +832,25 @@ public:
} }
// Saturation instructions // Saturation instructions
std::string arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { std::string arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
return fmt::format("ssat{} {}, #{}, {}{}", CondToString(cond), d, sat_imm + 1, n, ShiftStr(ShiftType(sh << 1), imm5)); const u32 bit_position = sat_imm.ZeroExtend() + 1;
return fmt::format("ssat{} {}, #{}, {}{}",
CondToString(cond), d, bit_position, n,
ShiftStr(ShiftType(sh << 1), imm5));
} }
std::string arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { std::string arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
return fmt::format("ssat16{} {}, #{}, {}", CondToString(cond), d, sat_imm + 1, n); const u32 bit_position = sat_imm.ZeroExtend() + 1;
return fmt::format("ssat16{} {}, #{}, {}",
CondToString(cond), d, bit_position, n);
} }
std::string arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { std::string arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
return fmt::format("usat{} {}, #{}, {}{}", CondToString(cond), d, sat_imm, n, ShiftStr(ShiftType(sh << 1), imm5)); return fmt::format("usat{} {}, #{}, {}{}",
CondToString(cond), d, sat_imm.ZeroExtend(), n,
ShiftStr(ShiftType(sh << 1), imm5));
} }
std::string arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { std::string arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
return fmt::format("usat16{} {}, #{}, {}", CondToString(cond), d, sat_imm, n); return fmt::format("usat16{} {}, #{}, {}",
CondToString(cond), d, sat_imm.ZeroExtend(), n);
} }
// Divide instructions // Divide instructions
@ -940,19 +1107,31 @@ public:
std::string arm_MRS(Cond cond, Reg d) { std::string arm_MRS(Cond cond, Reg d) {
return fmt::format("mrs{} {}, apsr", CondToString(cond), d); return fmt::format("mrs{} {}, apsr", CondToString(cond), d);
} }
std::string arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8) { std::string arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8) {
const bool write_c = Common::Bit<0>(mask); const bool write_c = Common::Bit<0>(mask);
const bool write_x = Common::Bit<1>(mask); const bool write_x = Common::Bit<1>(mask);
const bool write_s = Common::Bit<2>(mask); const bool write_s = Common::Bit<2>(mask);
const bool write_f = Common::Bit<3>(mask); const bool write_f = Common::Bit<3>(mask);
return fmt::format("msr{} cpsr_{}{}{}{}, #{}", CondToString(cond), write_c ? "c" : "", write_x ? "x" : "", write_s ? "s" : "", write_f ? "f" : "", ArmExpandImm(rotate, imm8)); return fmt::format("msr{} cpsr_{}{}{}{}, #{}",
CondToString(cond),
write_c ? "c" : "",
write_x ? "x" : "",
write_s ? "s" : "",
write_f ? "f" : "",
ArmExpandImm(rotate, imm8));
} }
std::string arm_MSR_reg(Cond cond, int mask, Reg n) { std::string arm_MSR_reg(Cond cond, int mask, Reg n) {
const bool write_c = Common::Bit<0>(mask); const bool write_c = Common::Bit<0>(mask);
const bool write_x = Common::Bit<1>(mask); const bool write_x = Common::Bit<1>(mask);
const bool write_s = Common::Bit<2>(mask); const bool write_s = Common::Bit<2>(mask);
const bool write_f = Common::Bit<3>(mask); const bool write_f = Common::Bit<3>(mask);
return fmt::format("msr{} cpsr_{}{}{}{}, {}", CondToString(cond), write_c ? "c" : "", write_x ? "x" : "", write_s ? "s" : "", write_f ? "f" : "", n); return fmt::format("msr{} cpsr_{}{}{}{}, {}",
CondToString(cond),
write_c ? "c" : "",
write_x ? "x" : "",
write_s ? "s" : "",
write_f ? "f" : "",
n);
} }
std::string arm_RFE() { return "ice"; } std::string arm_RFE() { return "ice"; }
std::string arm_SETEND(bool E) { std::string arm_SETEND(bool E) {
@ -1080,52 +1259,83 @@ public:
} }
} }
std::string vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) { std::string vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
return fmt::format("vpop{} {}(+{})", CondToString(cond), FPRegStr(sz, Vd, D), imm8 >> (sz ? 1 : 0)); return fmt::format("vpop{} {}(+{})",
CondToString(cond), FPRegStr(sz, Vd, D),
imm8.ZeroExtend() >> (sz ? 1 : 0));
} }
std::string vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) { std::string vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
return fmt::format("vpush{} {}(+{})", CondToString(cond), FPRegStr(sz, Vd, D), imm8 >> (sz ? 1 : 0)); return fmt::format("vpush{} {}(+{})",
CondToString(cond), FPRegStr(sz, Vd, D),
imm8.ZeroExtend() >> (sz ? 1 : 0));
} }
std::string vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) { std::string vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("vldr{} {}, [{}, #{}{}]", CondToString(cond), FPRegStr(sz, Vd, D), n, U ? '+' : '-', imm32); const char sign = U ? '+' : '-';
return fmt::format("vldr{} {}, [{}, #{}{}]",
CondToString(cond), FPRegStr(sz, Vd, D), n, sign, imm32);
} }
std::string vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) { std::string vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("vstr{} {}, [{}, #{}{}]", CondToString(cond), FPRegStr(sz, Vd, D), n, U ? '+' : '-', imm32); const char sign = U ? '+' : '-';
return fmt::format("vstr{} {}, [{}, #{}{}]",
CondToString(cond), FPRegStr(sz, Vd, D), n, sign, imm32);
} }
std::string vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { std::string vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
const char* mode = "<invalid mode>"; const char* mode = "<invalid mode>";
if (!p && u) mode = "ia"; if (!p && u) {
if (p && !u) mode = "db"; mode = "ia";
return fmt::format("vstm{}{}.f64 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(true, Vd, D), imm8); }
if (p && !u) {
mode = "db";
}
return fmt::format("vstm{}{}.f64 {}{}, {}(+{})", mode,
CondToString(cond), n, w ? "!" : "",
FPRegStr(true, Vd, D), imm8.ZeroExtend());
} }
std::string vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { std::string vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
const char* mode = "<invalid mode>"; const char* mode = "<invalid mode>";
if (!p && u) mode = "ia"; if (!p && u) {
if (p && !u) mode = "db"; mode = "ia";
return fmt::format("vstm{}{}.f32 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(false, Vd, D), imm8); }
if (p && !u) {
mode = "db";
}
return fmt::format("vstm{}{}.f32 {}{}, {}(+{})", mode,
CondToString(cond), n, w ? "!" : "",
FPRegStr(false, Vd, D), imm8.ZeroExtend());
} }
std::string vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { std::string vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
const char* mode = "<invalid mode>"; const char* mode = "<invalid mode>";
if (!p && u) mode = "ia"; if (!p && u) {
if (p && !u) mode = "db"; mode = "ia";
return fmt::format("vldm{}{}.f64 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(true, Vd, D), imm8); }
if (p && !u) {
mode = "db";
}
return fmt::format("vldm{}{}.f64 {}{}, {}(+{})", mode,
CondToString(cond), n, w ? "!" : "",
FPRegStr(true, Vd, D), imm8.ZeroExtend());
} }
std::string vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { std::string vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
const char* mode = "<invalid mode>"; const char* mode = "<invalid mode>";
if (!p && u) mode = "ia"; if (!p && u) {
if (p && !u) mode = "db"; mode = "ia";
return fmt::format("vldm{}{}.f32 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(false, Vd, D), imm8); }
if (p && !u) {
mode = "db";
}
return fmt::format("vldm{}{}.f32 {}{}, {}(+{})", mode,
CondToString(cond), n, w ? "!" : "",
FPRegStr(false, Vd, D), imm8.ZeroExtend());
} }
}; };
std::string DisassembleArm(u32 instruction) { std::string DisassembleArm(u32 instruction) {

View file

@ -12,6 +12,7 @@
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "frontend/imm.h"
#include "frontend/A32/decoder/thumb16.h" #include "frontend/A32/decoder/thumb16.h"
#include "frontend/A32/disassembler/disassembler.h" #include "frontend/A32/disassembler/disassembler.h"
#include "frontend/A32/types.h" #include "frontend/A32/types.h"
@ -22,16 +23,18 @@ class DisassemblerVisitor {
public: public:
using instruction_return_type = std::string; using instruction_return_type = std::string;
std::string thumb16_LSL_imm(Imm5 imm5, Reg m, Reg d) { std::string thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) {
return fmt::format("lsls {}, {}, #{}", d, m, imm5); return fmt::format("lsls {}, {}, #{}", d, m, imm5.ZeroExtend());
} }
std::string thumb16_LSR_imm(Imm5 imm5, Reg m, Reg d) { std::string thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) {
return fmt::format("lsrs {}, {}, #{}", d, m, imm5 != 0 ? imm5 : 32); const u32 shift = imm5 != 0 ? imm5.ZeroExtend() : 32U;
return fmt::format("lsrs {}, {}, #{}", d, m, shift);
} }
std::string thumb16_ASR_imm(Imm5 imm5, Reg m, Reg d) { std::string thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
return fmt::format("asrs {}, {}, #{}", d, m, imm5 != 0 ? imm5 : 32); const u32 shift = imm5 != 0 ? imm5.ZeroExtend() : 32U;
return fmt::format("asrs {}, {}, #{}", d, m, shift);
} }
std::string thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) { std::string thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) {
@ -42,28 +45,28 @@ public:
return fmt::format("subs {}, {}, {}", d, n, m); return fmt::format("subs {}, {}, {}", d, n, m);
} }
std::string thumb16_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) { std::string thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) {
return fmt::format("adds {}, {}, #{}", d, n, imm3); return fmt::format("adds {}, {}, #{}", d, n, imm3.ZeroExtend());
} }
std::string thumb16_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) { std::string thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d) {
return fmt::format("subs {}, {}, #{}", d, n, imm3); return fmt::format("subs {}, {}, #{}", d, n, imm3.ZeroExtend());
} }
std::string thumb16_MOV_imm(Reg d, Imm8 imm8) { std::string thumb16_MOV_imm(Reg d, Imm<8> imm8) {
return fmt::format("movs {}, #{}", d, imm8); return fmt::format("movs {}, #{}", d, imm8.ZeroExtend());
} }
std::string thumb16_CMP_imm(Reg n, Imm8 imm8) { std::string thumb16_CMP_imm(Reg n, Imm<8> imm8) {
return fmt::format("cmp {}, #{}", n, imm8); return fmt::format("cmp {}, #{}", n, imm8.ZeroExtend());
} }
std::string thumb16_ADD_imm_t2(Reg d_n, Imm8 imm8) { std::string thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) {
return fmt::format("adds {}, #{}", d_n, imm8); return fmt::format("adds {}, #{}", d_n, imm8.ZeroExtend());
} }
std::string thumb16_SUB_imm_t2(Reg d_n, Imm8 imm8) { std::string thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8) {
return fmt::format("subs {}, #{}", d_n, imm8); return fmt::format("subs {}, #{}", d_n, imm8.ZeroExtend());
} }
std::string thumb16_AND_reg(Reg m, Reg d_n) { std::string thumb16_AND_reg(Reg m, Reg d_n) {
@ -132,22 +135,22 @@ public:
} }
std::string thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { std::string thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) {
Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo; const Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;
return fmt::format("add {}, {}", d_n, m); return fmt::format("add {}, {}", d_n, m);
} }
std::string thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) { std::string thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) {
Reg n = n_hi ? (n_lo + 8) : n_lo; const Reg n = n_hi ? (n_lo + 8) : n_lo;
return fmt::format("cmp {}, {}", n, m); return fmt::format("cmp {}, {}", n, m);
} }
std::string thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) { std::string thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) {
Reg d = d_hi ? (d_lo + 8) : d_lo; const Reg d = d_hi ? (d_lo + 8) : d_lo;
return fmt::format("mov {}, {}", d, m); return fmt::format("mov {}, {}", d, m);
} }
std::string thumb16_LDR_literal(Reg t, Imm8 imm8) { std::string thumb16_LDR_literal(Reg t, Imm<8> imm8) {
u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("ldr {}, [pc, #{}]", t, imm32); return fmt::format("ldr {}, [pc, #{}]", t, imm32);
} }
@ -183,63 +186,63 @@ public:
return fmt::format("ldrsh {}, [{}, {}]", t, n, m); return fmt::format("ldrsh {}, [{}, {}]", t, n, m);
} }
std::string thumb16_STR_imm_t1(Imm5 imm5, Reg n, Reg t) { std::string thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
u32 imm32 = imm5 << 2; const u32 imm32 = imm5.ZeroExtend() << 2;
return fmt::format("str {}, [{}, #{}]", t, n, imm32); return fmt::format("str {}, [{}, #{}]", t, n, imm32);
} }
std::string thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) { std::string thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
u32 imm32 = imm5 << 2; const u32 imm32 = imm5.ZeroExtend() << 2;
return fmt::format("ldr {}, [{}, #{}]", t, n, imm32); return fmt::format("ldr {}, [{}, #{}]", t, n, imm32);
} }
std::string thumb16_STRB_imm(Imm5 imm5, Reg n, Reg t) { std::string thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) {
u32 imm32 = imm5; const u32 imm32 = imm5.ZeroExtend();
return fmt::format("strb {}, [{}, #{}]", t, n, imm32); return fmt::format("strb {}, [{}, #{}]", t, n, imm32);
} }
std::string thumb16_LDRB_imm(Imm5 imm5, Reg n, Reg t) { std::string thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t) {
u32 imm32 = imm5; const u32 imm32 = imm5.ZeroExtend();
return fmt::format("ldrb {}, [{}, #{}]", t, n, imm32); return fmt::format("ldrb {}, [{}, #{}]", t, n, imm32);
} }
std::string thumb16_STRH_imm(Imm5 imm5, Reg n, Reg t) { std::string thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) {
u32 imm32 = imm5 << 1; const u32 imm32 = imm5.ZeroExtend() << 1;
return fmt::format("strh {}, [{}, #{}]", t, n, imm32); return fmt::format("strh {}, [{}, #{}]", t, n, imm32);
} }
std::string thumb16_LDRH_imm(Imm5 imm5, Reg n, Reg t) { std::string thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t) {
u32 imm32 = imm5 << 1; const u32 imm32 = imm5.ZeroExtend() << 1;
return fmt::format("ldrh {}, [{}, #{}]", t, n, imm32); return fmt::format("ldrh {}, [{}, #{}]", t, n, imm32);
} }
std::string thumb16_STR_imm_t2(Reg t, Imm5 imm5) { std::string thumb16_STR_imm_t2(Reg t, Imm<8> imm8) {
u32 imm32 = imm5 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("str {}, [sp, #{}]", t, imm32); return fmt::format("str {}, [sp, #{}]", t, imm32);
} }
std::string thumb16_LDR_imm_t2(Reg t, Imm5 imm5) { std::string thumb16_LDR_imm_t2(Reg t, Imm<8> imm8) {
u32 imm32 = imm5 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("ldr {}, [sp, #{}]", t, imm32); return fmt::format("ldr {}, [sp, #{}]", t, imm32);
} }
std::string thumb16_ADR(Reg d, Imm8 imm8) { std::string thumb16_ADR(Reg d, Imm<8> imm8) {
u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("adr {}, +#{}", d, imm32); return fmt::format("adr {}, +#{}", d, imm32);
} }
std::string thumb16_ADD_sp_t1(Reg d, Imm8 imm8) { std::string thumb16_ADD_sp_t1(Reg d, Imm<8> imm8) {
u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
return fmt::format("add {}, sp, #{}", d, imm32); return fmt::format("add {}, sp, #{}", d, imm32);
} }
std::string thumb16_ADD_sp_t2(Imm7 imm7) { std::string thumb16_ADD_sp_t2(Imm<7> imm7) {
u32 imm32 = imm7 << 2; const u32 imm32 = imm7.ZeroExtend() << 2;
return fmt::format("add sp, sp, #{}", imm32); return fmt::format("add sp, sp, #{}", imm32);
} }
std::string thumb16_SUB_sp(Imm7 imm7) { std::string thumb16_SUB_sp(Imm<7> imm7) {
u32 imm32 = imm7 << 2; const u32 imm32 = imm7.ZeroExtend() << 2;
return fmt::format("sub sp, sp, #{}", imm32); return fmt::format("sub sp, sp, #{}", imm32);
} }
@ -294,7 +297,7 @@ public:
} }
std::string thumb16_LDMIA(Reg n, RegList reg_list) { std::string thumb16_LDMIA(Reg n, RegList reg_list) {
bool write_back = !Common::Bit(static_cast<size_t>(n), reg_list); const bool write_back = !Common::Bit(static_cast<size_t>(n), reg_list);
return fmt::format("ldm {}{}, {{{}}}", n, write_back ? "!" : "", RegListToString(reg_list)); return fmt::format("ldm {}{}, {{{}}}", n, write_back ? "!" : "", RegListToString(reg_list));
} }
@ -310,18 +313,23 @@ public:
return fmt::format("udf"); return fmt::format("udf");
} }
std::string thumb16_SVC(Imm8 imm8) { std::string thumb16_SVC(Imm<8> imm8) {
return fmt::format("svc #{}", imm8); return fmt::format("svc #{}", imm8.ZeroExtend());
} }
std::string thumb16_B_t1(Cond cond, Imm8 imm8) { std::string thumb16_B_t1(Cond cond, Imm<8> imm8) {
s32 imm32 = Common::SignExtend<9, s32>(imm8 << 1) + 4; const s32 imm32 = static_cast<s32>((imm8.SignExtend<u32>() << 1) + 4);
return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(imm32), abs(imm32)); return fmt::format("b{} {}#{}",
CondToString(cond),
Common::SignToChar(imm32),
abs(imm32));
} }
std::string thumb16_B_t2(Imm11 imm11) { std::string thumb16_B_t2(Imm<11> imm11) {
s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4; const s32 imm32 = static_cast<s32>((imm11.SignExtend<u32>() << 1) + 4);
return fmt::format("b {}#{}", Common::SignToChar(imm32), abs(imm32)); return fmt::format("b {}#{}",
Common::SignToChar(imm32),
abs(imm32));
} }
}; };

View file

@ -157,22 +157,26 @@ bool ArmTranslatorVisitor::UndefinedInstruction() {
return false; return false;
} }
IR::ResultAndCarry<IR::U32> ArmTranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm5 imm5, IR::U1 carry_in) { IR::ResultAndCarry<IR::U32> ArmTranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in) {
u8 imm5_value = imm5.ZeroExtend<u8>();
switch (type) { switch (type) {
case ShiftType::LSL: case ShiftType::LSL:
return ir.LogicalShiftLeft(value, ir.Imm8(imm5), carry_in); return ir.LogicalShiftLeft(value, ir.Imm8(imm5_value), carry_in);
case ShiftType::LSR: case ShiftType::LSR:
imm5 = imm5 ? imm5 : 32; imm5_value = imm5_value ? imm5_value : 32;
return ir.LogicalShiftRight(value, ir.Imm8(imm5), carry_in); return ir.LogicalShiftRight(value, ir.Imm8(imm5_value), carry_in);
case ShiftType::ASR: case ShiftType::ASR:
imm5 = imm5 ? imm5 : 32; imm5_value = imm5_value ? imm5_value : 32;
return ir.ArithmeticShiftRight(value, ir.Imm8(imm5), carry_in); return ir.ArithmeticShiftRight(value, ir.Imm8(imm5_value), carry_in);
case ShiftType::ROR: case ShiftType::ROR:
if (imm5) if (imm5_value) {
return ir.RotateRight(value, ir.Imm8(imm5), carry_in); return ir.RotateRight(value, ir.Imm8(imm5_value), carry_in);
else } else {
return ir.RotateRightExtended(value, carry_in); return ir.RotateRightExtended(value, carry_in);
} }
}
UNREACHABLE(); UNREACHABLE();
return {}; return {};
} }

View file

@ -8,17 +8,17 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
bool ArmTranslatorVisitor::arm_DMB([[maybe_unused]] Imm4 option) { bool ArmTranslatorVisitor::arm_DMB([[maybe_unused]] Imm<4> option) {
ir.DataMemoryBarrier(); ir.DataMemoryBarrier();
return true; return true;
} }
bool ArmTranslatorVisitor::arm_DSB([[maybe_unused]] Imm4 option) { bool ArmTranslatorVisitor::arm_DSB([[maybe_unused]] Imm<4> option) {
ir.DataSynchronizationBarrier(); ir.DataSynchronizationBarrier();
return true; return true;
} }
bool ArmTranslatorVisitor::arm_ISB([[maybe_unused]] Imm4 option) { bool ArmTranslatorVisitor::arm_ISB([[maybe_unused]] Imm<4> option) {
ir.InstructionSynchronizationBarrier(); ir.InstructionSynchronizationBarrier();
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4)); ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
ir.SetTerm(IR::Term::ReturnToDispatch{}); ir.SetTerm(IR::Term::ReturnToDispatch{});

View file

@ -11,19 +11,19 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
// B <label> // B <label>
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) { bool ArmTranslatorVisitor::arm_B(Cond cond, Imm<24> imm24) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
const u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8; const u32 imm32 = Common::SignExtend<26, u32>(imm24.ZeroExtend() << 2) + 8;
const auto new_location = ir.current_location.AdvancePC(imm32); const auto new_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{new_location}); ir.SetTerm(IR::Term::LinkBlock{new_location});
return false; return false;
} }
// BL <label> // BL <label>
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) { bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm<24> imm24) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -31,18 +31,18 @@ bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
ir.PushRSB(ir.current_location.AdvancePC(4)); ir.PushRSB(ir.current_location.AdvancePC(4));
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4)); ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
const u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8; const u32 imm32 = Common::SignExtend<26, u32>(imm24.ZeroExtend() << 2) + 8;
const auto new_location = ir.current_location.AdvancePC(imm32); const auto new_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{new_location}); ir.SetTerm(IR::Term::LinkBlock{new_location});
return false; return false;
} }
// BLX <label> // BLX <label>
bool ArmTranslatorVisitor::arm_BLX_imm(bool H, Imm24 imm24) { bool ArmTranslatorVisitor::arm_BLX_imm(bool H, Imm<24> imm24) {
ir.PushRSB(ir.current_location.AdvancePC(4)); ir.PushRSB(ir.current_location.AdvancePC(4));
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4)); ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
const u32 imm32 = Common::SignExtend<26, u32>((imm24 << 2)) + (H ? 2 : 0) + 8; const u32 imm32 = Common::SignExtend<26, u32>((imm24.ZeroExtend() << 2)) + (H ? 2 : 0) + 8;
const auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true); const auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true);
ir.SetTerm(IR::Term::LinkBlock{new_location}); ir.SetTerm(IR::Term::LinkBlock{new_location});
return false; return false;

View file

@ -25,7 +25,7 @@ bool ArmTranslatorVisitor::arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, Coproc
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>, #+/-<imm32>]{!} // LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>, #+/-<imm32>]{!}
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], #+/-<imm32> // LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], #+/-<imm32>
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], <imm8> // LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], <imm8>
bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) { bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
if (!p && !u && !d && !w) { if (!p && !u && !d && !w) {
return arm_UDF(); return arm_UDF();
} }
@ -37,7 +37,7 @@ bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Re
const bool two = cond == Cond::NV; const bool two = cond == Cond::NV;
if (two || ConditionPassed(cond)) { if (two || ConditionPassed(cond)) {
const u32 imm32 = static_cast<u8>(imm8) << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const bool index = p; const bool index = p;
const bool add = u; const bool add = u;
const bool wback = w; const bool wback = w;
@ -45,7 +45,7 @@ bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Re
const IR::U32 reg_n = ir.GetRegister(n); const IR::U32 reg_n = ir.GetRegister(n);
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32)); const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
const IR::U32 address = index ? offset_address : reg_n; const IR::U32 address = index ? offset_address : reg_n;
ir.CoprocLoadWords(coproc_no, two, d, CRd, address, has_option, imm8); ir.CoprocLoadWords(coproc_no, two, d, CRd, address, has_option, imm8.ZeroExtend<u8>());
if (wback) { if (wback) {
ir.SetRegister(n, offset_address); ir.SetRegister(n, offset_address);
} }
@ -132,7 +132,7 @@ bool ArmTranslatorVisitor::arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no,
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>, #+/-<imm32>]{!} // STC{2}{L}<c> <coproc>, <CRd>, [<Rn>, #+/-<imm32>]{!}
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], #+/-<imm32> // STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], #+/-<imm32>
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], <imm8> // STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], <imm8>
bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) { bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
if ((coproc_no & 0b1110) == 0b1010) { if ((coproc_no & 0b1110) == 0b1010) {
return arm_UDF(); return arm_UDF();
} }
@ -148,7 +148,7 @@ bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Re
const bool two = cond == Cond::NV; const bool two = cond == Cond::NV;
if (two || ConditionPassed(cond)) { if (two || ConditionPassed(cond)) {
const u32 imm32 = static_cast<u8>(imm8) << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const bool index = p; const bool index = p;
const bool add = u; const bool add = u;
const bool wback = w; const bool wback = w;
@ -156,7 +156,7 @@ bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Re
const IR::U32 reg_n = ir.GetRegister(n); const IR::U32 reg_n = ir.GetRegister(n);
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32)); const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
const IR::U32 address = index ? offset_address : reg_n; const IR::U32 address = index ? offset_address : reg_n;
ir.CoprocStoreWords(coproc_no, two, d, CRd, address, has_option, imm8); ir.CoprocStoreWords(coproc_no, two, d, CRd, address, has_option, imm8.ZeroExtend<u8>());
if (wback) { if (wback) {
ir.SetRegister(n, offset_address); ir.SetRegister(n, offset_address);
} }

View file

@ -9,7 +9,7 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
// ADC{S}<c> <Rd>, <Rn>, #<imm> // ADC{S}<c> <Rd>, <Rn>, #<imm>
bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -38,7 +38,7 @@ bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -94,7 +94,7 @@ bool ArmTranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// ADD{S}<c> <Rd>, <Rn>, #<const> // ADD{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -124,7 +124,7 @@ bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -180,7 +180,7 @@ bool ArmTranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// AND{S}<c> <Rd>, <Rn>, #<const> // AND{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -209,7 +209,7 @@ bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -263,7 +263,7 @@ bool ArmTranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// BIC{S}<c> <Rd>, <Rn>, #<const> // BIC{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -292,7 +292,7 @@ bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -347,7 +347,7 @@ bool ArmTranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// CMN<c> <Rn>, #<const> // CMN<c> <Rn>, #<const>
bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -363,7 +363,7 @@ bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
} }
// CMN<c> <Rn>, <Rm>{, <shift>} // CMN<c> <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -401,7 +401,7 @@ bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
} }
// CMP<c> <Rn>, #<imm> // CMP<c> <Rn>, #<imm>
bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -417,7 +417,7 @@ bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
} }
// CMP<c> <Rn>, <Rm>{, <shift>} // CMP<c> <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -455,7 +455,7 @@ bool ArmTranslatorVisitor::arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
} }
// EOR{S}<c> <Rd>, <Rn>, #<const> // EOR{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -484,7 +484,7 @@ bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -539,7 +539,7 @@ bool ArmTranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// MOV{S}<c> <Rd>, #<const> // MOV{S}<c> <Rd>, #<const>
bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -568,7 +568,7 @@ bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm
} }
// MOV{S}<c> <Rd>, <Rm> // MOV{S}<c> <Rd>, <Rm>
bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -621,7 +621,7 @@ bool ArmTranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftTyp
} }
// MVN{S}<c> <Rd>, #<const> // MVN{S}<c> <Rd>, #<const>
bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -650,7 +650,7 @@ bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm
} }
// MVN{S}<c> <Rd>, <Rm>{, <shift>} // MVN{S}<c> <Rd>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -705,7 +705,7 @@ bool ArmTranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftTyp
} }
// ORR{S}<c> <Rd>, <Rn>, #<const> // ORR{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -734,7 +734,7 @@ bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -789,7 +789,7 @@ bool ArmTranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// RSB{S}<c> <Rd>, <Rn>, #<const> // RSB{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -819,7 +819,7 @@ bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -875,7 +875,7 @@ bool ArmTranslatorVisitor::arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// RSC{S}<c> <Rd>, <Rn>, #<const> // RSC{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -904,7 +904,7 @@ bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rota
return true; return true;
} }
bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -960,7 +960,7 @@ bool ArmTranslatorVisitor::arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// SBC{S}<c> <Rd>, <Rn>, #<const> // SBC{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -990,7 +990,7 @@ bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -1046,7 +1046,7 @@ bool ArmTranslatorVisitor::arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// SUB{S}<c> <Rd>, <Rn>, #<const> // SUB{S}<c> <Rd>, <Rn>, #<const>
bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -1076,7 +1076,7 @@ bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rota
} }
// SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>} // SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -1131,7 +1131,7 @@ bool ArmTranslatorVisitor::arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
} }
// TEQ<c> <Rn>, #<const> // TEQ<c> <Rn>, #<const>
bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -1146,7 +1146,7 @@ bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
} }
// TEQ<c> <Rn>, <Rm>{, <shift>} // TEQ<c> <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -1183,7 +1183,7 @@ bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
} }
// TST<c> <Rn>, #<const> // TST<c> <Rn>, #<const>
bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
@ -1198,7 +1198,7 @@ bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
} }
// TST<c> <Rn>, <Rm>{, <shift>} // TST<c> <Rn>, <Rm>{, <shift>}
bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }

View file

@ -11,7 +11,7 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
// BKPT #<imm16> // BKPT #<imm16>
bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm12 /*imm12*/, Imm4 /*imm4*/) { bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) {
if (cond != Cond::AL && !options.define_unpredictable_behaviour) { if (cond != Cond::AL && !options.define_unpredictable_behaviour) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -27,12 +27,12 @@ bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm12 /*imm12*/, Imm4 /*imm4*/) {
} }
// SVC<c> #<imm24> // SVC<c> #<imm24>
bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) { bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm<24> imm24) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
const u32 imm32 = imm24; const u32 imm32 = imm24.ZeroExtend();
ir.PushRSB(ir.current_location.AdvancePC(4)); ir.PushRSB(ir.current_location.AdvancePC(4));
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4)); ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
ir.CallSupervisor(ir.Imm32(imm32)); ir.CallSupervisor(ir.Imm32(imm32));

View file

@ -56,14 +56,14 @@ static IR::U32 GetAddress(A32::IREmitter& ir, bool P, bool U, bool W, Reg n, IR:
} }
// LDR <Rt>, [PC, #+/-<imm>] // LDR <Rt>, [PC, #+/-<imm>]
bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) { bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
const bool add = U; const bool add = U;
const u32 base = ir.AlignPC(4); const u32 base = ir.AlignPC(4);
const u32 address = add ? (base + imm12) : (base - imm12); const u32 address = add ? (base + imm12.ZeroExtend()) : (base - imm12.ZeroExtend());
const auto data = ir.ReadMemory32(ir.Imm32(address)); const auto data = ir.ReadMemory32(ir.Imm32(address));
if (t == Reg::PC) { if (t == Reg::PC) {
@ -78,7 +78,7 @@ bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
// LDR <Rt>, [<Rn>, #+/-<imm>]{!} // LDR <Rt>, [<Rn>, #+/-<imm>]{!}
// LDR <Rt>, [<Rn>], #+/-<imm> // LDR <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
if (n == Reg::PC) { if (n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -92,7 +92,7 @@ bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n,
return true; return true;
} }
const u32 imm32 = imm12; const u32 imm32 = imm12.ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
const auto data = ir.ReadMemory32(address); const auto data = ir.ReadMemory32(address);
@ -115,7 +115,7 @@ bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n,
// LDR <Rt>, [<Rn>, #+/-<Rm>]{!} // LDR <Rt>, [<Rn>, #+/-<Rm>]{!}
// LDR <Rt>, [<Rn>], #+/-<Rm> // LDR <Rt>, [<Rn>], #+/-<Rm>
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
if (m == Reg::PC) { if (m == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -144,7 +144,7 @@ bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n,
} }
// LDRB <Rt>, [PC, #+/-<imm>] // LDRB <Rt>, [PC, #+/-<imm>]
bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) { bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
if (t == Reg::PC) { if (t == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -153,7 +153,7 @@ bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
return true; return true;
} }
const u32 imm32 = imm12; const u32 imm32 = imm12.ZeroExtend();
const bool add = U; const bool add = U;
const u32 base = ir.AlignPC(4); const u32 base = ir.AlignPC(4);
const u32 address = add ? (base + imm32) : (base - imm32); const u32 address = add ? (base + imm32) : (base - imm32);
@ -165,7 +165,7 @@ bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
// LDRB <Rt>, [<Rn>, #+/-<imm>]{!} // LDRB <Rt>, [<Rn>, #+/-<imm>]{!}
// LDRB <Rt>, [<Rn>], #+/-<imm> // LDRB <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
if (n == Reg::PC) { if (n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -183,7 +183,7 @@ bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n
return true; return true;
} }
const u32 imm32 = imm12; const u32 imm32 = imm12.ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
@ -194,7 +194,7 @@ bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n
// LDRB <Rt>, [<Rn>, #+/-<Rm>]{!} // LDRB <Rt>, [<Rn>, #+/-<Rm>]{!}
// LDRB <Rt>, [<Rn>], #+/-<Rm> // LDRB <Rt>, [<Rn>], #+/-<Rm>
bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
if (t == Reg::PC || m == Reg::PC) { if (t == Reg::PC || m == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -217,7 +217,7 @@ bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n
} }
// LDRD <Rt>, <Rt2>, [PC, #+/-<imm>] // LDRD <Rt>, <Rt2>, [PC, #+/-<imm>]
bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (RegNumber(t) % 2 == 1) { if (RegNumber(t) % 2 == 1) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -231,7 +231,7 @@ bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Im
} }
const Reg t2 = t+1; const Reg t2 = t+1;
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U; const bool add = U;
const u32 base = ir.AlignPC(4); const u32 base = ir.AlignPC(4);
@ -246,7 +246,7 @@ bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Im
// LDRD <Rt>, [<Rn>, #+/-<imm>]{!} // LDRD <Rt>, [<Rn>, #+/-<imm>]{!}
// LDRD <Rt>, [<Rn>], #+/-<imm> // LDRD <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (n == Reg::PC) { if (n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -272,7 +272,7 @@ bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n
} }
const Reg t2 = t+1; const Reg t2 = t+1;
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address_a = GetAddress(ir, P, U, W, n, offset); const auto address_a = GetAddress(ir, P, U, W, n, offset);
@ -321,7 +321,7 @@ bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n
} }
// LDRH <Rt>, [PC, #-/+<imm>] // LDRH <Rt>, [PC, #-/+<imm>]
bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
if (P == W) { if (P == W) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -335,7 +335,7 @@ bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t
return true; return true;
} }
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U; const bool add = U;
const u32 base = ir.AlignPC(4); const u32 base = ir.AlignPC(4);
const u32 address = add ? (base + imm32) : (base - imm32); const u32 address = add ? (base + imm32) : (base - imm32);
@ -347,7 +347,7 @@ bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t
// LDRH <Rt>, [<Rn>, #+/-<imm>]{!} // LDRH <Rt>, [<Rn>, #+/-<imm>]{!}
// LDRH <Rt>, [<Rn>], #+/-<imm> // LDRH <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (n == Reg::PC) { if (n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -365,7 +365,7 @@ bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n
return true; return true;
} }
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
@ -399,7 +399,7 @@ bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n
} }
// LDRSB <Rt>, [PC, #+/-<imm>] // LDRSB <Rt>, [PC, #+/-<imm>]
bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (t == Reg::PC) { if (t == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -408,7 +408,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
return true; return true;
} }
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U; const bool add = U;
const u32 base = ir.AlignPC(4); const u32 base = ir.AlignPC(4);
@ -421,7 +421,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
// LDRSB <Rt>, [<Rn>, #+/-<imm>]{!} // LDRSB <Rt>, [<Rn>, #+/-<imm>]{!}
// LDRSB <Rt>, [<Rn>], #+/-<imm> // LDRSB <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (n == Reg::PC) { if (n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -439,7 +439,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg
return true; return true;
} }
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address));
@ -473,7 +473,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg
} }
// LDRSH <Rt>, [PC, #-/+<imm>] // LDRSH <Rt>, [PC, #-/+<imm>]
bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (t == Reg::PC) { if (t == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -482,7 +482,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
return true; return true;
} }
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U; const bool add = U;
const u32 base = ir.AlignPC(4); const u32 base = ir.AlignPC(4);
const u32 address = add ? (base + imm32) : (base - imm32); const u32 address = add ? (base + imm32) : (base - imm32);
@ -494,7 +494,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
// LDRSH <Rt>, [<Rn>, #+/-<imm>]{!} // LDRSH <Rt>, [<Rn>, #+/-<imm>]{!}
// LDRSH <Rt>, [<Rn>], #+/-<imm> // LDRSH <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (n == Reg::PC) { if (n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -512,7 +512,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg
return true; return true;
} }
const u32 imm32 = (imm8a << 4) | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address));
@ -547,7 +547,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg
// STR <Rt>, [<Rn>, #+/-<imm>]{!} // STR <Rt>, [<Rn>, #+/-<imm>]{!}
// STR <Rt>, [<Rn>], #+/-<imm> // STR <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
if ((!P || W) && (n == Reg::PC || n == t)) { if ((!P || W) && (n == Reg::PC || n == t)) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -556,7 +556,7 @@ bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n,
return true; return true;
} }
const auto offset = ir.Imm32(imm12); const auto offset = ir.Imm32(imm12.ZeroExtend());
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
ir.WriteMemory32(address, ir.GetRegister(t)); ir.WriteMemory32(address, ir.GetRegister(t));
return true; return true;
@ -564,7 +564,7 @@ bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n,
// STR <Rt>, [<Rn>, #+/-<Rm>]{!} // STR <Rt>, [<Rn>, #+/-<Rm>]{!}
// STR <Rt>, [<Rn>], #+/-<Rm> // STR <Rt>, [<Rn>], #+/-<Rm>
bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
if (m == Reg::PC) { if (m == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -585,7 +585,7 @@ bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n,
// STRB <Rt>, [<Rn>, #+/-<imm>]{!} // STRB <Rt>, [<Rn>, #+/-<imm>]{!}
// STRB <Rt>, [<Rn>], #+/-<imm> // STRB <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
if (t == Reg::PC) { if (t == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -598,7 +598,7 @@ bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n
return true; return true;
} }
const auto offset = ir.Imm32(imm12); const auto offset = ir.Imm32(imm12.ZeroExtend());
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);
ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)));
return true; return true;
@ -606,7 +606,7 @@ bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n
// STRB <Rt>, [<Rn>, #+/-<Rm>]{!} // STRB <Rt>, [<Rn>, #+/-<Rm>]{!}
// STRB <Rt>, [<Rn>], #+/-<Rm> // STRB <Rt>, [<Rn>], #+/-<Rm>
bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
if (t == Reg::PC || m == Reg::PC) { if (t == Reg::PC || m == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -627,7 +627,7 @@ bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n
// STRD <Rt>, [<Rn>, #+/-<imm>]{!} // STRD <Rt>, [<Rn>, #+/-<imm>]{!}
// STRD <Rt>, [<Rn>], #+/-<imm> // STRD <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (size_t(t) % 2 != 0) { if (size_t(t) % 2 != 0) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -649,7 +649,7 @@ bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n
return true; return true;
} }
const u32 imm32 = imm8a << 4 | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address_a = GetAddress(ir, P, U, W, n, offset); const auto address_a = GetAddress(ir, P, U, W, n, offset);
const auto address_b = ir.Add(address_a, ir.Imm32(4)); const auto address_b = ir.Add(address_a, ir.Imm32(4));
@ -698,7 +698,7 @@ bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n
// STRH <Rt>, [<Rn>, #+/-<imm>]{!} // STRH <Rt>, [<Rn>, #+/-<imm>]{!}
// STRH <Rt>, [<Rn>], #+/-<imm> // STRH <Rt>, [<Rn>], #+/-<imm>
bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
if (t == Reg::PC) { if (t == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -711,7 +711,7 @@ bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n
return true; return true;
} }
const u32 imm32 = imm8a << 4 | imm8b; const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32); const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset); const auto address = GetAddress(ir, P, U, W, n, offset);

View file

@ -10,7 +10,7 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
// BFC<c> <Rd>, #<lsb>, #<width> // BFC<c> <Rd>, #<lsb>, #<width>
bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) { bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb) {
if (d == Reg::PC) { if (d == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -22,7 +22,9 @@ bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
return true; return true;
} }
const u32 mask = ~(Common::Ones<u32>(msb - lsb + 1) << lsb); const u32 lsb_value = lsb.ZeroExtend();
const u32 msb_value = msb.ZeroExtend();
const u32 mask = ~(Common::Ones<u32>(msb_value - lsb_value + 1) << lsb_value);
const IR::U32 operand = ir.GetRegister(d); const IR::U32 operand = ir.GetRegister(d);
const IR::U32 result = ir.And(operand, ir.Imm32(mask)); const IR::U32 result = ir.And(operand, ir.Imm32(mask));
@ -31,7 +33,7 @@ bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
} }
// BFI<c> <Rd>, <Rn>, #<lsb>, #<width> // BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n) { bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n) {
if (d == Reg::PC) { if (d == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -43,10 +45,12 @@ bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n)
return true; return true;
} }
const u32 inclusion_mask = Common::Ones<u32>(msb - lsb + 1) << lsb; const u32 lsb_value = lsb.ZeroExtend();
const u32 msb_value = msb.ZeroExtend();
const u32 inclusion_mask = Common::Ones<u32>(msb_value - lsb_value + 1) << lsb_value;
const u32 exclusion_mask = ~inclusion_mask; const u32 exclusion_mask = ~inclusion_mask;
const IR::U32 operand1 = ir.And(ir.GetRegister(d), ir.Imm32(exclusion_mask)); const IR::U32 operand1 = ir.And(ir.GetRegister(d), ir.Imm32(exclusion_mask));
const IR::U32 operand2 = ir.And(ir.LogicalShiftLeft(ir.GetRegister(n), ir.Imm8(lsb)), ir.Imm32(inclusion_mask)); const IR::U32 operand2 = ir.And(ir.LogicalShiftLeft(ir.GetRegister(n), ir.Imm8(u8(lsb_value))), ir.Imm32(inclusion_mask));
const IR::U32 result = ir.Or(operand1, operand2); const IR::U32 result = ir.Or(operand1, operand2);
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -68,7 +72,7 @@ bool ArmTranslatorVisitor::arm_CLZ(Cond cond, Reg d, Reg m) {
} }
// MOVT<c> <Rd>, #<imm16> // MOVT<c> <Rd>, #<imm16>
bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) { bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12) {
if (d == Reg::PC) { if (d == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -77,7 +81,7 @@ bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
return true; return true;
} }
const IR::U32 imm16 = ir.Imm32(((u32(imm4) << 12 | u32(imm12)) << 16)); const IR::U32 imm16 = ir.Imm32(concatenate(imm4, imm12).ZeroExtend() << 16);
const IR::U32 operand = ir.GetRegister(d); const IR::U32 operand = ir.GetRegister(d);
const IR::U32 result = ir.Or(ir.And(operand, ir.Imm32(0x0000FFFFU)), imm16); const IR::U32 result = ir.Or(ir.And(operand, ir.Imm32(0x0000FFFFU)), imm16);
@ -86,12 +90,14 @@ bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
} }
// SBFX<c> <Rd>, <Rn>, #<lsb>, #<width> // SBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
bool ArmTranslatorVisitor::arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) { bool ArmTranslatorVisitor::arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
if (d == Reg::PC || n == Reg::PC) { if (d == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
const u32 msb = u32{lsb} + widthm1; const u32 lsb_value = lsb.ZeroExtend();
const u32 widthm1_value = widthm1.ZeroExtend();
const u32 msb = lsb_value + widthm1_value;
if (msb >= Common::BitSize<u32>()) { if (msb >= Common::BitSize<u32>()) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -101,8 +107,8 @@ bool ArmTranslatorVisitor::arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Re
} }
constexpr size_t max_width = Common::BitSize<u32>(); constexpr size_t max_width = Common::BitSize<u32>();
const u8 width = widthm1 + 1; const u32 width = widthm1_value + 1;
const u8 left_shift_amount = static_cast<u8>(max_width - width - lsb); const u8 left_shift_amount = static_cast<u8>(max_width - width - lsb_value);
const u8 right_shift_amount = static_cast<u8>(max_width - width); const u8 right_shift_amount = static_cast<u8>(max_width - width);
const IR::U32 operand = ir.GetRegister(n); const IR::U32 operand = ir.GetRegister(n);
const IR::U32 tmp = ir.LogicalShiftLeft(operand, ir.Imm8(left_shift_amount)); const IR::U32 tmp = ir.LogicalShiftLeft(operand, ir.Imm8(left_shift_amount));
@ -131,12 +137,14 @@ bool ArmTranslatorVisitor::arm_SEL(Cond cond, Reg n, Reg d, Reg m) {
} }
// UBFX<c> <Rd>, <Rn>, #<lsb>, #<width> // UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
bool ArmTranslatorVisitor::arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) { bool ArmTranslatorVisitor::arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
if (d == Reg::PC || n == Reg::PC) { if (d == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
const u32 msb = u32{lsb} + widthm1; const u32 lsb_value = lsb.ZeroExtend();
const u32 widthm1_value = widthm1.ZeroExtend();
const u32 msb = lsb_value + widthm1_value;
if (msb >= Common::BitSize<u32>()) { if (msb >= Common::BitSize<u32>()) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -146,8 +154,8 @@ bool ArmTranslatorVisitor::arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Re
} }
const IR::U32 operand = ir.GetRegister(n); const IR::U32 operand = ir.GetRegister(n);
const IR::U32 mask = ir.Imm32(Common::Ones<u32>(widthm1 + 1)); const IR::U32 mask = ir.Imm32(Common::Ones<u32>(widthm1_value + 1));
const IR::U32 result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(lsb)), mask); const IR::U32 result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(u8(lsb_value))), mask);
ir.SetRegister(d, result); ir.SetRegister(d, result);
return true; return true;

View file

@ -9,7 +9,7 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
// PKHBT<c> <Rd>, <Rn>, <Rm>{, LSL #<imm>} // PKHBT<c> <Rd>, <Rn>, <Rm>{, LSL #<imm>}
bool ArmTranslatorVisitor::arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) { bool ArmTranslatorVisitor::arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
if (n == Reg::PC || d == Reg::PC || m == Reg::PC) { if (n == Reg::PC || d == Reg::PC || m == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -27,7 +27,7 @@ bool ArmTranslatorVisitor::arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m)
} }
// PKHTB<c> <Rd>, <Rn>, <Rm>{, ASR #<imm>} // PKHTB<c> <Rd>, <Rn>, <Rm>{, ASR #<imm>}
bool ArmTranslatorVisitor::arm_PKHTB(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) { bool ArmTranslatorVisitor::arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
if (n == Reg::PC || d == Reg::PC || m == Reg::PC) { if (n == Reg::PC || d == Reg::PC || m == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }

View file

@ -19,7 +19,7 @@ static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
// Saturation instructions // Saturation instructions
// SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>} // SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
if (d == Reg::PC || n == Reg::PC) { if (d == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -28,7 +28,7 @@ bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
return true; return true;
} }
const auto saturate_to = static_cast<size_t>(sat_imm) + 1; const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend()) + 1;
const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR; const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR;
const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag()); const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
const auto result = ir.SignedSaturation(operand.result, saturate_to); const auto result = ir.SignedSaturation(operand.result, saturate_to);
@ -39,7 +39,7 @@ bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
} }
// SSAT16<c> <Rd>, #<imm>, <Rn> // SSAT16<c> <Rd>, #<imm>, <Rn>
bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
if (d == Reg::PC || n == Reg::PC) { if (d == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -48,7 +48,7 @@ bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
return true; return true;
} }
const auto saturate_to = static_cast<size_t>(sat_imm) + 1; const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend()) + 1;
const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n))); const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n)));
const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n))); const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
const auto lo_result = ir.SignedSaturation(lo_operand, saturate_to); const auto lo_result = ir.SignedSaturation(lo_operand, saturate_to);
@ -61,7 +61,7 @@ bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
} }
// USAT<c> <Rd>, #<imm5>, <Rn>{, <shift>} // USAT<c> <Rd>, #<imm5>, <Rn>{, <shift>}
bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
if (d == Reg::PC || n == Reg::PC) { if (d == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -70,7 +70,7 @@ bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
return true; return true;
} }
const auto saturate_to = static_cast<size_t>(sat_imm); const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend());
const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR; const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR;
const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag()); const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
const auto result = ir.UnsignedSaturation(operand.result, saturate_to); const auto result = ir.UnsignedSaturation(operand.result, saturate_to);
@ -81,7 +81,7 @@ bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
} }
// USAT16<c> <Rd>, #<imm4>, <Rn> // USAT16<c> <Rd>, #<imm4>, <Rn>
bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
if (d == Reg::PC || n == Reg::PC) { if (d == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
@ -91,7 +91,7 @@ bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
} }
// UnsignedSaturation takes a *signed* value as input, hence sign extension is required. // UnsignedSaturation takes a *signed* value as input, hence sign extension is required.
const auto saturate_to = static_cast<size_t>(sat_imm); const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend());
const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n))); const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n)));
const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n))); const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
const auto lo_result = ir.UnsignedSaturation(lo_operand, saturate_to); const auto lo_result = ir.UnsignedSaturation(lo_operand, saturate_to);

View file

@ -31,7 +31,7 @@ bool ArmTranslatorVisitor::arm_MRS(Cond cond, Reg d) {
} }
// MSR<c> <spec_reg>, #<const> // MSR<c> <spec_reg>, #<const>
bool ArmTranslatorVisitor::arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8) { bool ArmTranslatorVisitor::arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8) {
ASSERT_MSG(mask != 0, "Decode error"); ASSERT_MSG(mask != 0, "Decode error");
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {

View file

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "common/bit_util.h" #include "common/bit_util.h"
#include "frontend/imm.h"
#include "frontend/A32/ir_emitter.h" #include "frontend/A32/ir_emitter.h"
#include "frontend/A32/location_descriptor.h" #include "frontend/A32/location_descriptor.h"
#include "frontend/A32/translate/translate.h" #include "frontend/A32/translate/translate.h"
@ -40,8 +41,8 @@ struct ArmTranslatorVisitor final {
bool UnpredictableInstruction(); bool UnpredictableInstruction();
bool UndefinedInstruction(); bool UndefinedInstruction();
static u32 ArmExpandImm(int rotate, Imm8 imm8) { static u32 ArmExpandImm(int rotate, Imm<8> imm8) {
return Common::RotateRight<u32>(imm8, rotate * 2); return Common::RotateRight<u32>(imm8.ZeroExtend(), rotate * 2);
} }
struct ImmAndCarry { struct ImmAndCarry {
@ -49,96 +50,96 @@ struct ArmTranslatorVisitor final {
IR::U1 carry; IR::U1 carry;
}; };
ImmAndCarry ArmExpandImm_C(int rotate, u32 imm8, IR::U1 carry_in) { ImmAndCarry ArmExpandImm_C(int rotate, Imm<8> imm8, IR::U1 carry_in) {
u32 imm32 = imm8; u32 imm32 = imm8.ZeroExtend();
auto carry_out = carry_in; auto carry_out = carry_in;
if (rotate) { if (rotate) {
imm32 = ArmExpandImm(rotate, static_cast<Imm8>(imm8)); imm32 = ArmExpandImm(rotate, imm8);
carry_out = ir.Imm1(Common::Bit<31>(imm32)); carry_out = ir.Imm1(Common::Bit<31>(imm32));
} }
return {imm32, carry_out}; return {imm32, carry_out};
} }
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm5 imm5, IR::U1 carry_in); IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in);
IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in); IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in);
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn); template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn); template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);
// Barrier instructions // Barrier instructions
bool arm_DMB(Imm4 option); bool arm_DMB(Imm<4> option);
bool arm_DSB(Imm4 option); bool arm_DSB(Imm<4> option);
bool arm_ISB(Imm4 option); bool arm_ISB(Imm<4> option);
// Branch instructions // Branch instructions
bool arm_B(Cond cond, Imm24 imm24); bool arm_B(Cond cond, Imm<24> imm24);
bool arm_BL(Cond cond, Imm24 imm24); bool arm_BL(Cond cond, Imm<24> imm24);
bool arm_BLX_imm(bool H, Imm24 imm24); bool arm_BLX_imm(bool H, Imm<24> imm24);
bool arm_BLX_reg(Cond cond, Reg m); bool arm_BLX_reg(Cond cond, Reg m);
bool arm_BX(Cond cond, Reg m); bool arm_BX(Cond cond, Reg m);
bool arm_BXJ(Cond cond, Reg m); bool arm_BXJ(Cond cond, Reg m);
// Coprocessor instructions // Coprocessor instructions
bool arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm); bool arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
bool arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8); bool arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
bool arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm); bool arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
bool arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm); bool arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
bool arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm); bool arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
bool arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm); bool arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
bool arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8); bool arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
// Data processing instructions // Data processing instructions
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8); bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
bool arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); bool arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8); bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
bool arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); bool arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8); bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8);
bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m); bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8); bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8);
bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m); bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8); bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
bool arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); bool arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8); bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
bool arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); bool arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
// Exception generating instructions // Exception generating instructions
bool arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4); bool arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4);
bool arm_SVC(Cond cond, Imm24 imm24); bool arm_SVC(Cond cond, Imm<24> imm24);
bool arm_UDF(); bool arm_UDF();
// Extension instructions // Extension instructions
@ -171,31 +172,31 @@ struct ArmTranslatorVisitor final {
bool arm_STRBT(); bool arm_STRBT();
bool arm_STRHT(); bool arm_STRHT();
bool arm_STRT(); bool arm_STRT();
bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12); bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12);
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12); bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm<12> imm12);
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12); bool arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12);
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12); bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m); bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m); bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
bool arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m); bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
bool arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m); bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
bool arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m); bool arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
bool arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12); bool arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m); bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12); bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m); bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m); bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m); bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
// Load/Store multiple instructions // Load/Store multiple instructions
@ -212,23 +213,23 @@ struct ArmTranslatorVisitor final {
bool arm_STM_usr(); bool arm_STM_usr();
// Miscellaneous instructions // Miscellaneous instructions
bool arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb); bool arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb);
bool arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n); bool arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n);
bool arm_CLZ(Cond cond, Reg d, Reg m); bool arm_CLZ(Cond cond, Reg d, Reg m);
bool arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12); bool arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
bool arm_NOP() { return true; } bool arm_NOP() { return true; }
bool arm_RBIT(Cond cond, Reg d, Reg m); bool arm_RBIT(Cond cond, Reg d, Reg m);
bool arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n); bool arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m); bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
bool arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n); bool arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
// Unsigned sum of absolute difference functions // Unsigned sum of absolute difference functions
bool arm_USAD8(Cond cond, Reg d, Reg m, Reg n); bool arm_USAD8(Cond cond, Reg d, Reg m, Reg n);
bool arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n); bool arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n);
// Packing instructions // Packing instructions
bool arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m); bool arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m);
bool arm_PKHTB(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m); bool arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m);
// Reversal instructions // Reversal instructions
bool arm_REV(Cond cond, Reg d, Reg m); bool arm_REV(Cond cond, Reg d, Reg m);
@ -236,10 +237,10 @@ struct ArmTranslatorVisitor final {
bool arm_REVSH(Cond cond, Reg d, Reg m); bool arm_REVSH(Cond cond, Reg d, Reg m);
// Saturation instructions // Saturation instructions
bool arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n); bool arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n);
bool arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n); bool arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n);
bool arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n); bool arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n);
bool arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n); bool arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n);
// Divide instructions // Divide instructions
bool arm_SDIV(Cond cond, Reg d, Reg m, Reg n); bool arm_SDIV(Cond cond, Reg d, Reg m, Reg n);
@ -343,7 +344,7 @@ struct ArmTranslatorVisitor final {
// Status register access instructions // Status register access instructions
bool arm_CPS(); bool arm_CPS();
bool arm_MRS(Cond cond, Reg d); bool arm_MRS(Cond cond, Reg d);
bool arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8); bool arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8);
bool arm_MSR_reg(Cond cond, int mask, Reg n); bool arm_MSR_reg(Cond cond, int mask, Reg n);
bool arm_RFE(); bool arm_RFE();
bool arm_SETEND(bool E); bool arm_SETEND(bool E);
@ -387,14 +388,14 @@ struct ArmTranslatorVisitor final {
bool vfp2_VMRS(Cond cond, Reg t); bool vfp2_VMRS(Cond cond, Reg t);
// Floating-point load-store instructions // Floating-point load-store instructions
bool vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8); bool vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8);
bool vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8); bool vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8);
bool vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8); bool vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8);
bool vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8); bool vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8);
bool vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8); bool vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
bool vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8); bool vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
bool vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8); bool vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
bool vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8); bool vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
}; };
} // namespace Dynarmic::A32 } // namespace Dynarmic::A32

View file

@ -628,9 +628,9 @@ bool ArmTranslatorVisitor::vfp2_VMRS(Cond cond, Reg t) {
} }
// VPOP.{F32,F64} <list> // VPOP.{F32,F64} <list>
bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
const ExtReg d = ToExtReg(sz, Vd, D); const ExtReg d = ToExtReg(sz, Vd, D);
const size_t regs = sz ? imm8 >> 1 : imm8; const size_t regs = sz ? imm8.ZeroExtend() >> 1 : imm8.ZeroExtend();
if (regs == 0 || RegNumber(d)+regs > 32) { if (regs == 0 || RegNumber(d)+regs > 32) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -668,9 +668,9 @@ bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8
} }
// VPUSH.{F32,F64} <list> // VPUSH.{F32,F64} <list>
bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
const ExtReg d = ToExtReg(sz, Vd, D); const ExtReg d = ToExtReg(sz, Vd, D);
const size_t regs = sz ? imm8 >> 1 : imm8; const size_t regs = sz ? imm8.ZeroExtend() >> 1 : imm8.ZeroExtend();
if (regs == 0 || RegNumber(d)+regs > 32) { if (regs == 0 || RegNumber(d)+regs > 32) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -684,7 +684,7 @@ bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
auto address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(imm32)); auto address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(imm32));
ir.SetRegister(Reg::SP, address); ir.SetRegister(Reg::SP, address);
@ -709,12 +709,12 @@ bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm
// VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}] // VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
// VLDR<c> <Sd>, [<Rn>{, #+/-<imm>}] // VLDR<c> <Sd>, [<Rn>{, #+/-<imm>}]
bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const auto d = ToExtReg(sz, Vd, D); const auto d = ToExtReg(sz, Vd, D);
const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n); const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32)); const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
@ -735,12 +735,12 @@ bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd
// VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}] // VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
// VSTR<c> <Sd>, [<Rn>{, #+/-<imm>}] // VSTR<c> <Sd>, [<Rn>{, #+/-<imm>}]
bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
if (!ConditionPassed(cond)) { if (!ConditionPassed(cond)) {
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const auto d = ToExtReg(sz, Vd, D); const auto d = ToExtReg(sz, Vd, D);
const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n); const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32)); const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
@ -761,7 +761,7 @@ bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd
} }
// VSTM{mode}<c> <Rn>{!}, <list of double registers> // VSTM{mode}<c> <Rn>{!}, <list of double registers>
bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
if (!p && !u && !w) { if (!p && !u && !w) {
ASSERT_MSG(false, "Decode error"); ASSERT_MSG(false, "Decode error");
} }
@ -779,7 +779,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
} }
const auto d = ToExtReg(true, Vd, D); const auto d = ToExtReg(true, Vd, D);
const size_t regs = imm8 / 2; const size_t regs = imm8.ZeroExtend() / 2;
if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) { if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -789,7 +789,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32))); auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
if (w) { if (w) {
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
@ -813,7 +813,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
} }
// VSTM{mode}<c> <Rn>{!}, <list of single registers> // VSTM{mode}<c> <Rn>{!}, <list of single registers>
bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
if (!p && !u && !w) { if (!p && !u && !w) {
ASSERT_MSG(false, "Decode error"); ASSERT_MSG(false, "Decode error");
} }
@ -831,7 +831,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
} }
const auto d = ToExtReg(false, Vd, D); const auto d = ToExtReg(false, Vd, D);
const size_t regs = imm8; const size_t regs = imm8.ZeroExtend();
if (regs == 0 || A32::RegNumber(d)+regs > 32) { if (regs == 0 || A32::RegNumber(d)+regs > 32) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -841,7 +841,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32))); auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
if (w) { if (w) {
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
@ -856,7 +856,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
} }
// VLDM{mode}<c> <Rn>{!}, <list of double registers> // VLDM{mode}<c> <Rn>{!}, <list of double registers>
bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
if (!p && !u && !w) { if (!p && !u && !w) {
ASSERT_MSG(false, "Decode error"); ASSERT_MSG(false, "Decode error");
} }
@ -874,7 +874,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
} }
const auto d = ToExtReg(true, Vd, D); const auto d = ToExtReg(true, Vd, D);
const size_t regs = imm8 / 2; const size_t regs = imm8.ZeroExtend() / 2;
if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) { if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -884,7 +884,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32))); auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
if (w) { if (w) {
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
@ -906,7 +906,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
} }
// VLDM{mode}<c> <Rn>{!}, <list of single registers> // VLDM{mode}<c> <Rn>{!}, <list of single registers>
bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) { bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
if (!p && !u && !w) { if (!p && !u && !w) {
ASSERT_MSG(false, "Decode error"); ASSERT_MSG(false, "Decode error");
} }
@ -924,7 +924,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool
} }
const auto d = ToExtReg(false, Vd, D); const auto d = ToExtReg(false, Vd, D);
const size_t regs = imm8; const size_t regs = imm8.ZeroExtend();
if (regs == 0 || A32::RegNumber(d)+regs > 32) { if (regs == 0 || A32::RegNumber(d)+regs > 32) {
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -934,7 +934,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool
return true; return true;
} }
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32))); auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
if (w) { if (w) {
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);

View file

@ -8,6 +8,7 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h" #include "common/bit_util.h"
#include "frontend/imm.h"
#include "frontend/A32/decoder/thumb16.h" #include "frontend/A32/decoder/thumb16.h"
#include "frontend/A32/decoder/thumb32.h" #include "frontend/A32/decoder/thumb32.h"
#include "frontend/A32/ir_emitter.h" #include "frontend/A32/ir_emitter.h"
@ -39,8 +40,8 @@ struct ThumbTranslatorVisitor final {
} }
// LSLS <Rd>, <Rm>, #<imm5> // LSLS <Rd>, <Rm>, #<imm5>
bool thumb16_LSL_imm(Imm5 imm5, Reg m, Reg d) { bool thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) {
const u8 shift_n = imm5; const u8 shift_n = imm5.ZeroExtend<u8>();
const auto cpsr_c = ir.GetCFlag(); const auto cpsr_c = ir.GetCFlag();
const auto result = ir.LogicalShiftLeft(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c); const auto result = ir.LogicalShiftLeft(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
@ -52,8 +53,8 @@ struct ThumbTranslatorVisitor final {
} }
// LSRS <Rd>, <Rm>, #<imm5> // LSRS <Rd>, <Rm>, #<imm5>
bool thumb16_LSR_imm(Imm5 imm5, Reg m, Reg d) { bool thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) {
const u8 shift_n = imm5 != 0 ? imm5 : 32; const u8 shift_n = imm5 != 0 ? imm5.ZeroExtend<u8>() : u8(32);
const auto cpsr_c = ir.GetCFlag(); const auto cpsr_c = ir.GetCFlag();
const auto result = ir.LogicalShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c); const auto result = ir.LogicalShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
@ -65,8 +66,8 @@ struct ThumbTranslatorVisitor final {
} }
// ASRS <Rd>, <Rm>, #<imm5> // ASRS <Rd>, <Rm>, #<imm5>
bool thumb16_ASR_imm(Imm5 imm5, Reg m, Reg d) { bool thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
const u8 shift_n = imm5 != 0 ? imm5 : 32; const u8 shift_n = imm5 != 0 ? imm5.ZeroExtend<u8>() : u8(32);
const auto cpsr_c = ir.GetCFlag(); const auto cpsr_c = ir.GetCFlag();
const auto result = ir.ArithmeticShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c); const auto result = ir.ArithmeticShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
@ -103,8 +104,8 @@ struct ThumbTranslatorVisitor final {
// ADDS <Rd>, <Rn>, #<imm3> // ADDS <Rd>, <Rn>, #<imm3>
// Rd can never encode R15. // Rd can never encode R15.
bool thumb16_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) { bool thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) {
const u32 imm32 = imm3 & 0x7; const u32 imm32 = imm3.ZeroExtend();
const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
ir.SetRegister(d, result.result); ir.SetRegister(d, result.result);
@ -117,8 +118,8 @@ struct ThumbTranslatorVisitor final {
// SUBS <Rd>, <Rn>, #<imm3> // SUBS <Rd>, <Rn>, #<imm3>
// Rd can never encode R15. // Rd can never encode R15.
bool thumb16_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) { bool thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d) {
const u32 imm32 = imm3 & 0x7; const u32 imm32 = imm3.ZeroExtend();
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
ir.SetRegister(d, result.result); ir.SetRegister(d, result.result);
@ -131,8 +132,8 @@ struct ThumbTranslatorVisitor final {
// MOVS <Rd>, #<imm8> // MOVS <Rd>, #<imm8>
// Rd can never encode R15. // Rd can never encode R15.
bool thumb16_MOV_imm(Reg d, Imm8 imm8) { bool thumb16_MOV_imm(Reg d, Imm<8> imm8) {
const u32 imm32 = imm8 & 0xFF; const u32 imm32 = imm8.ZeroExtend();
const auto result = ir.Imm32(imm32); const auto result = ir.Imm32(imm32);
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -142,8 +143,8 @@ struct ThumbTranslatorVisitor final {
} }
// CMP <Rn>, #<imm8> // CMP <Rn>, #<imm8>
bool thumb16_CMP_imm(Reg n, Imm8 imm8) { bool thumb16_CMP_imm(Reg n, Imm<8> imm8) {
const u32 imm32 = imm8 & 0xFF; const u32 imm32 = imm8.ZeroExtend();
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
ir.SetNFlag(ir.MostSignificantBit(result.result)); ir.SetNFlag(ir.MostSignificantBit(result.result));
@ -155,8 +156,8 @@ struct ThumbTranslatorVisitor final {
// ADDS <Rdn>, #<imm8> // ADDS <Rdn>, #<imm8>
// Rd can never encode R15. // Rd can never encode R15.
bool thumb16_ADD_imm_t2(Reg d_n, Imm8 imm8) { bool thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) {
const u32 imm32 = imm8 & 0xFF; const u32 imm32 = imm8.ZeroExtend();
const Reg d = d_n; const Reg d = d_n;
const Reg n = d_n; const Reg n = d_n;
const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
@ -171,8 +172,8 @@ struct ThumbTranslatorVisitor final {
// SUBS <Rd>, <Rn>, #<imm3> // SUBS <Rd>, <Rn>, #<imm3>
// Rd can never encode R15. // Rd can never encode R15.
bool thumb16_SUB_imm_t2(Reg d_n, Imm8 imm8) { bool thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8) {
const u32 imm32 = imm8 & 0xFF; const u32 imm32 = imm8.ZeroExtend();
const Reg d = d_n; const Reg d = d_n;
const Reg n = d_n; const Reg n = d_n;
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
@ -448,8 +449,8 @@ struct ThumbTranslatorVisitor final {
// LDR <Rt>, <label> // LDR <Rt>, <label>
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_LDR_literal(Reg t, Imm8 imm8) { bool thumb16_LDR_literal(Reg t, Imm<8> imm8) {
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const u32 address = ir.AlignPC(4) + imm32; const u32 address = ir.AlignPC(4) + imm32;
const auto data = ir.ReadMemory32(ir.Imm32(address)); const auto data = ir.ReadMemory32(ir.Imm32(address));
@ -539,8 +540,8 @@ struct ThumbTranslatorVisitor final {
// STR <Rt>, [<Rn>, #<imm>] // STR <Rt>, [<Rn>, #<imm>]
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_STR_imm_t1(Imm5 imm5, Reg n, Reg t) { bool thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
const u32 imm32 = imm5 << 2; const u32 imm32 = imm5.ZeroExtend() << 2;
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.GetRegister(t); const auto data = ir.GetRegister(t);
@ -550,8 +551,8 @@ struct ThumbTranslatorVisitor final {
// LDR <Rt>, [<Rn>, #<imm>] // LDR <Rt>, [<Rn>, #<imm>]
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) { bool thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
const u32 imm32 = imm5 << 2; const u32 imm32 = imm5.ZeroExtend() << 2;
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.ReadMemory32(address); const auto data = ir.ReadMemory32(address);
@ -561,8 +562,8 @@ struct ThumbTranslatorVisitor final {
// STRB <Rt>, [<Rn>, #<imm>] // STRB <Rt>, [<Rn>, #<imm>]
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_STRB_imm(Imm5 imm5, Reg n, Reg t) { bool thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) {
const u32 imm32 = imm5; const u32 imm32 = imm5.ZeroExtend();
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.LeastSignificantByte(ir.GetRegister(t)); const auto data = ir.LeastSignificantByte(ir.GetRegister(t));
@ -572,8 +573,8 @@ struct ThumbTranslatorVisitor final {
// LDRB <Rt>, [<Rn>, #<imm>] // LDRB <Rt>, [<Rn>, #<imm>]
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_LDRB_imm(Imm5 imm5, Reg n, Reg t) { bool thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t) {
const u32 imm32 = imm5; const u32 imm32 = imm5.ZeroExtend();
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
@ -582,8 +583,8 @@ struct ThumbTranslatorVisitor final {
} }
// STRH <Rt>, [<Rn>, #<imm5>] // STRH <Rt>, [<Rn>, #<imm5>]
bool thumb16_STRH_imm(Imm5 imm5, Reg n, Reg t) { bool thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) {
const u32 imm32 = imm5 << 1; const u32 imm32 = imm5.ZeroExtend() << 1;
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.LeastSignificantHalf(ir.GetRegister(t)); const auto data = ir.LeastSignificantHalf(ir.GetRegister(t));
@ -592,8 +593,8 @@ struct ThumbTranslatorVisitor final {
} }
// LDRH <Rt>, [<Rn>, #<imm5>] // LDRH <Rt>, [<Rn>, #<imm5>]
bool thumb16_LDRH_imm(Imm5 imm5, Reg n, Reg t) { bool thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t) {
const u32 imm32 = imm5 << 1; const u32 imm32 = imm5.ZeroExtend() << 1;
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
@ -603,8 +604,8 @@ struct ThumbTranslatorVisitor final {
// STR <Rt>, [<Rn>, #<imm>] // STR <Rt>, [<Rn>, #<imm>]
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_STR_imm_t2(Reg t, Imm5 imm5) { bool thumb16_STR_imm_t2(Reg t, Imm<8> imm8) {
const u32 imm32 = imm5 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const Reg n = Reg::SP; const Reg n = Reg::SP;
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.GetRegister(t); const auto data = ir.GetRegister(t);
@ -615,8 +616,8 @@ struct ThumbTranslatorVisitor final {
// LDR <Rt>, [<Rn>, #<imm>] // LDR <Rt>, [<Rn>, #<imm>]
// Rt cannot encode R15. // Rt cannot encode R15.
bool thumb16_LDR_imm_t2(Reg t, Imm5 imm5) { bool thumb16_LDR_imm_t2(Reg t, Imm<8> imm8) {
const u32 imm32 = imm5 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const Reg n = Reg::SP; const Reg n = Reg::SP;
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
const auto data = ir.ReadMemory32(address); const auto data = ir.ReadMemory32(address);
@ -627,8 +628,8 @@ struct ThumbTranslatorVisitor final {
// ADR <Rd>, <label> // ADR <Rd>, <label>
// Rd cannot encode R15. // Rd cannot encode R15.
bool thumb16_ADR(Reg d, Imm8 imm8) { bool thumb16_ADR(Reg d, Imm<8> imm8) {
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const auto result = ir.Imm32(ir.AlignPC(4) + imm32); const auto result = ir.Imm32(ir.AlignPC(4) + imm32);
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -636,8 +637,8 @@ struct ThumbTranslatorVisitor final {
} }
// ADD <Rd>, SP, #<imm> // ADD <Rd>, SP, #<imm>
bool thumb16_ADD_sp_t1(Reg d, Imm8 imm8) { bool thumb16_ADD_sp_t1(Reg d, Imm<8> imm8) {
const u32 imm32 = imm8 << 2; const u32 imm32 = imm8.ZeroExtend() << 2;
const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0)); const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0));
ir.SetRegister(d, result.result); ir.SetRegister(d, result.result);
@ -645,8 +646,8 @@ struct ThumbTranslatorVisitor final {
} }
// ADD SP, SP, #<imm> // ADD SP, SP, #<imm>
bool thumb16_ADD_sp_t2(Imm7 imm7) { bool thumb16_ADD_sp_t2(Imm<7> imm7) {
const u32 imm32 = imm7 << 2; const u32 imm32 = imm7.ZeroExtend() << 2;
const Reg d = Reg::SP; const Reg d = Reg::SP;
const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0)); const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0));
@ -655,8 +656,8 @@ struct ThumbTranslatorVisitor final {
} }
// SUB SP, SP, #<imm> // SUB SP, SP, #<imm>
bool thumb16_SUB_sp(Imm7 imm7) { bool thumb16_SUB_sp(Imm<7> imm7) {
const u32 imm32 = imm7 << 2; const u32 imm32 = imm7.ZeroExtend() << 2;
const Reg d = Reg::SP; const Reg d = Reg::SP;
const auto result = ir.SubWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(1)); const auto result = ir.SubWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(1));
@ -861,8 +862,8 @@ struct ThumbTranslatorVisitor final {
} }
// SVC #<imm8> // SVC #<imm8>
bool thumb16_SVC(Imm8 imm8) { bool thumb16_SVC(Imm<8> imm8) {
const u32 imm32 = imm8; const u32 imm32 = imm8.ZeroExtend();
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2)); ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2));
ir.PushRSB(ir.current_location.AdvancePC(2)); ir.PushRSB(ir.current_location.AdvancePC(2));
ir.CallSupervisor(ir.Imm32(imm32)); ir.CallSupervisor(ir.Imm32(imm32));
@ -871,12 +872,12 @@ struct ThumbTranslatorVisitor final {
} }
// B<cond> <label> // B<cond> <label>
bool thumb16_B_t1(Cond cond, Imm8 imm8) { bool thumb16_B_t1(Cond cond, Imm<8> imm8) {
if (cond == Cond::AL) { if (cond == Cond::AL) {
return thumb16_UDF(); return thumb16_UDF();
} }
const s32 imm32 = Common::SignExtend<9, s32>(imm8 << 1) + 4; const s32 imm32 = static_cast<s32>((imm8.SignExtend<u32>() << 1) + 4);
const auto then_location = ir.current_location.AdvancePC(imm32); const auto then_location = ir.current_location.AdvancePC(imm32);
const auto else_location = ir.current_location.AdvancePC(2); const auto else_location = ir.current_location.AdvancePC(2);
@ -885,8 +886,8 @@ struct ThumbTranslatorVisitor final {
} }
// B <label> // B <label>
bool thumb16_B_t2(Imm11 imm11) { bool thumb16_B_t2(Imm<11> imm11) {
const s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4; const s32 imm32 = static_cast<s32>((imm11.SignExtend<u32>() << 1) + 4);
const auto next_location = ir.current_location.AdvancePC(imm32); const auto next_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{next_location}); ir.SetTerm(IR::Term::LinkBlock{next_location});
@ -894,26 +895,26 @@ struct ThumbTranslatorVisitor final {
} }
// BL <label> // BL <label>
bool thumb32_BL_imm(Imm11 hi, Imm11 lo) { bool thumb32_BL_imm(Imm<11> hi, Imm<11> lo) {
ir.PushRSB(ir.current_location.AdvancePC(4)); ir.PushRSB(ir.current_location.AdvancePC(4));
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1)); ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
const s32 imm32 = Common::SignExtend<23, s32>((hi << 12) | (lo << 1)) + 4; const s32 imm32 = static_cast<s32>((concatenate(hi, lo).SignExtend<u32>() << 1) + 4);
const auto new_location = ir.current_location.AdvancePC(imm32); const auto new_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{new_location}); ir.SetTerm(IR::Term::LinkBlock{new_location});
return false; return false;
} }
// BLX <label> // BLX <label>
bool thumb32_BLX_imm(Imm11 hi, Imm11 lo) { bool thumb32_BLX_imm(Imm<11> hi, Imm<11> lo) {
if ((lo & 1) != 0) { if (lo.Bit<0>()) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
ir.PushRSB(ir.current_location.AdvancePC(4)); ir.PushRSB(ir.current_location.AdvancePC(4));
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1)); ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
const s32 imm32 = Common::SignExtend<23, s32>((hi << 12) | (lo << 1)); const s32 imm32 = static_cast<s32>(concatenate(hi, lo).SignExtend<u32>() << 1);
const auto new_location = ir.current_location const auto new_location = ir.current_location
.SetPC(ir.AlignPC(4) + imm32) .SetPC(ir.AlignPC(4) + imm32)
.SetTFlag(false); .SetTFlag(false);

View file

@ -39,14 +39,6 @@ enum class ExtReg {
D24, D25, D26, D27, D28, D29, D30, D31, D24, D25, D26, D27, D28, D29, D30, D31,
}; };
using Imm3 = u8;
using Imm4 = u8;
using Imm5 = u8;
using Imm7 = u8;
using Imm8 = u8;
using Imm11 = u16;
using Imm12 = u16;
using Imm24 = u32;
using RegList = u16; using RegList = u16;
enum class ShiftType { enum class ShiftType {