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/string_util.h"
#include "frontend/imm.h"
#include "frontend/A32/decoder/arm.h"
#include "frontend/A32/decoder/vfp2.h"
#include "frontend/A32/disassembler/disassembler.h"
@ -23,24 +24,24 @@ class DisassemblerVisitor {
public:
using instruction_return_type = std::string;
static u32 ArmExpandImm(int rotate, Imm8 imm8) {
return Common::RotateRight(static_cast<u32>(imm8), rotate*2);
static u32 ArmExpandImm(int rotate, Imm<8> imm8) {
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) {
case ShiftType::LSL:
if (imm5 == 0) return "";
return fmt::format(", lsl #{}", imm5);
return fmt::format(", lsl #{}", imm5.ZeroExtend());
case ShiftType::LSR:
if (imm5 == 0) return ", lsr #32";
return fmt::format(", lsr #{}", imm5);
return fmt::format(", lsr #{}", imm5.ZeroExtend());
case ShiftType::ASR:
if (imm5 == 0) return ", asr #32";
return fmt::format(", asr #{}", imm5);
return fmt::format(", asr #{}", imm5.ZeroExtend());
case ShiftType::ROR:
if (imm5 == 0) return ", rrx";
return fmt::format(", ror #{}", imm5);
return fmt::format(", ror #{}", imm5.ZeroExtend());
}
ASSERT(false);
return "<internal error>";
@ -76,8 +77,8 @@ public:
return "<internal error>";
}
static const char* BarrierOptionStr(Imm4 option) {
switch (option) {
static const char* BarrierOptionStr(Imm<4> option) {
switch (option.ZeroExtend()) {
case 0b0010:
return " oshst";
case 0b0011:
@ -124,27 +125,27 @@ public:
}
// Barrier instructions
std::string arm_DMB(Imm4 option) {
std::string arm_DMB(Imm<4> 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));
}
std::string arm_ISB([[maybe_unused]] Imm4 option) {
std::string arm_ISB([[maybe_unused]] Imm<4> option) {
return "isb";
}
// Branch instructions
std::string arm_B(Cond cond, Imm24 imm24) {
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
std::string arm_B(Cond cond, Imm<24> imm24) {
const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8;
return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
}
std::string arm_BL(Cond cond, Imm24 imm24) {
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
std::string arm_BL(Cond cond, Imm<24> imm24) {
const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8;
return fmt::format("bl{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
}
std::string arm_BLX_imm(bool H, Imm24 imm24) {
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8 + (H ? 2 : 0);
std::string arm_BLX_imm(bool H, Imm<24> imm24) {
const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8 + (H ? 2 : 0);
return fmt::format("blx {}#{}", Common::SignToChar(offset), abs(offset));
}
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);
}
std::string arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
const u32 imm32 = static_cast<u32>(imm8) << 2;
if (!p && !u && !d && !w)
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.ZeroExtend()) << 2;
if (!p && !u && !d && !w) {
return "<undefined>";
if (p)
return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : "");
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);
}
if (p) {
return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "",
CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32,
w ? "!" : "");
}
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();
return "<internal error>";
}
@ -192,160 +201,169 @@ public:
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) {
const u32 imm32 = static_cast<u32>(imm8) << 2;
if (!p && !u && !d && !w)
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.ZeroExtend()) << 2;
if (!p && !u && !d && !w) {
return "<undefined>";
if (p)
return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : "");
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);
}
if (p) {
return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "",
CondOrTwo(cond), coproc_no, CRd, n,
u ? "+" : "-", imm32, w ? "!" : "");
}
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();
return "<internal error>";
}
// 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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
std::string arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
@ -353,11 +371,11 @@ public:
}
// Exception generation instructions
std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) {
return fmt::format("bkpt{} #{}", CondToString(cond), imm12 << 4 | imm4);
std::string arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4) {
return fmt::format("bkpt{} #{}", CondToString(cond), concatenate(imm12, imm4).ZeroExtend());
}
std::string arm_SVC(Cond cond, Imm24 imm24) {
return fmt::format("svc{} #{}", CondToString(cond), imm24);
std::string arm_SVC(Cond cond, Imm<24> imm24) {
return fmt::format("svc{} #{}", CondToString(cond), imm24.ZeroExtend());
}
std::string arm_UDF() {
return fmt::format("udf");
@ -409,179 +427,307 @@ public:
std::string arm_YIELD() { return "yield <unimplemented>"; }
// 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;
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) {
return fmt::format("ldr{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
return fmt::format("ldr{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign,
imm12_value, W ? "!" : "");
} 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) {
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 {
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) {
bool P = true, W = false;
std::string arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
const bool P = true;
const bool W = false;
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) {
return fmt::format("ldrb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
return fmt::format("ldrb{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm12_value,
W ? "!" : "");
} 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) {
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 {
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_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
bool P = true, W = false;
std::string arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const bool P = true;
const bool W = false;
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) {
u32 imm32 = (imm8a << 4) | imm8b;
std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
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 {
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) {
const char sign = U ? '+' : '-';
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 {
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);
}
std::string arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
u32 imm32 = (imm8a << 4) | imm8b;
std::string arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
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 {
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) {
const char sign = U ? '+' : '-';
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 {
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_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
bool P = true, W = false;
std::string arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const bool P = true;
const bool W = false;
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) {
u32 imm32 = (imm8a << 4) | imm8b;
std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
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 {
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) {
const char sign = U ? '+' : '-';
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 {
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_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
bool P = true, W = false;
std::string arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const bool P = true;
const bool W = false;
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) {
u32 imm32 = (imm8a << 4) | imm8b;
std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
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 {
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) {
const char sign = U ? '+' : '-';
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 {
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_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) {
return fmt::format("str{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
return fmt::format("str{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm12_value,
W ? "!" : "");
} 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) {
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 {
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) {
return fmt::format("strb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
return fmt::format("strb{} {}, [{}, #{}{}]{}",
CondToString(cond), t, n, sign, imm12_value,
W ? "!" : "");
} 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) {
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 {
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_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
u32 imm32 = (imm8a << 4) | imm8b;
std::string arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
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 {
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) {
const char sign = U ? '+' : '-';
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 {
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) {
u32 imm32 = (imm8a << 4) | imm8b;
std::string arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const char sign = U ? '+' : '-';
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 {
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) {
const char sign = U ? '+' : '-';
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 {
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"; }
@ -617,17 +763,24 @@ public:
std::string arm_STM_usr() { return "ice"; }
// Miscellaneous instructions
std::string arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
return fmt::format("bfc{} {}, #{}, #{}", CondToString(cond), d, lsb, msb - lsb + 1);
std::string arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb) {
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) {
return fmt::format("bfi{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, msb - lsb + 1);
std::string arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n) {
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) {
return fmt::format("clz{} {}, {}", CondToString(cond), d, m);
}
std::string arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
return fmt::format("movt{} {}, #{}", CondToString(cond), d, (imm4 << 12) | imm12);
std::string arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12) {
const u32 imm = concatenate(imm4, imm12).ZeroExtend();
return fmt::format("movt{} {}, #{}", CondToString(cond), d, imm);
}
std::string arm_NOP() {
return "nop";
@ -635,14 +788,20 @@ public:
std::string arm_RBIT(Cond cond, Reg d, Reg m) {
return fmt::format("rbit{} {}, {}", CondToString(cond), d, m);
}
std::string arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) {
return fmt::format("sbfx{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, widthm1 + 1);
std::string arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
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) {
return fmt::format("sel{} {}, {}, {}", CondToString(cond), d, n, m);
}
std::string arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) {
return fmt::format("ubfx{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, widthm1 + 1);
std::string arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
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
@ -654,10 +813,10 @@ public:
}
// 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));
}
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));
}
@ -673,17 +832,25 @@ public:
}
// Saturation instructions
std::string arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) {
return fmt::format("ssat{} {}, #{}, {}{}", CondToString(cond), d, sat_imm + 1, n, ShiftStr(ShiftType(sh << 1), imm5));
std::string arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
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) {
return fmt::format("ssat16{} {}, #{}, {}", CondToString(cond), d, sat_imm + 1, n);
std::string arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg 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) {
return fmt::format("usat{} {}, #{}, {}{}", CondToString(cond), d, sat_imm, n, ShiftStr(ShiftType(sh << 1), imm5));
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.ZeroExtend(), n,
ShiftStr(ShiftType(sh << 1), imm5));
}
std::string arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
return fmt::format("usat16{} {}, #{}, {}", CondToString(cond), d, sat_imm, n);
std::string arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
return fmt::format("usat16{} {}, #{}, {}",
CondToString(cond), d, sat_imm.ZeroExtend(), n);
}
// Divide instructions
@ -940,19 +1107,31 @@ public:
std::string arm_MRS(Cond cond, Reg 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_x = Common::Bit<1>(mask);
const bool write_s = Common::Bit<2>(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) {
const bool write_c = Common::Bit<0>(mask);
const bool write_x = Common::Bit<1>(mask);
const bool write_s = Common::Bit<2>(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_SETEND(bool E) {
@ -1080,52 +1259,83 @@ public:
}
}
std::string vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) {
return fmt::format("vpop{} {}(+{})", CondToString(cond), FPRegStr(sz, Vd, D), imm8 >> (sz ? 1 : 0));
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.ZeroExtend() >> (sz ? 1 : 0));
}
std::string vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) {
return fmt::format("vpush{} {}(+{})", CondToString(cond), FPRegStr(sz, Vd, D), imm8 >> (sz ? 1 : 0));
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.ZeroExtend() >> (sz ? 1 : 0));
}
std::string vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) {
u32 imm32 = imm8 << 2;
return fmt::format("vldr{} {}, [{}, #{}{}]", CondToString(cond), FPRegStr(sz, Vd, D), n, U ? '+' : '-', imm32);
std::string vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
const u32 imm32 = imm8.ZeroExtend() << 2;
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) {
u32 imm32 = imm8 << 2;
return fmt::format("vstr{} {}, [{}, #{}{}]", CondToString(cond), FPRegStr(sz, Vd, D), n, U ? '+' : '-', imm32);
std::string vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
const u32 imm32 = imm8.ZeroExtend() << 2;
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>";
if (!p && u) mode = "ia";
if (p && !u) mode = "db";
return fmt::format("vstm{}{}.f64 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(true, Vd, D), imm8);
if (!p && u) {
mode = "ia";
}
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>";
if (!p && u) mode = "ia";
if (p && !u) mode = "db";
return fmt::format("vstm{}{}.f32 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(false, Vd, D), imm8);
if (!p && u) {
mode = "ia";
}
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>";
if (!p && u) mode = "ia";
if (p && !u) mode = "db";
return fmt::format("vldm{}{}.f64 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(true, Vd, D), imm8);
if (!p && u) {
mode = "ia";
}
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>";
if (!p && u) mode = "ia";
if (p && !u) mode = "db";
return fmt::format("vldm{}{}.f32 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(false, Vd, D), imm8);
if (!p && u) {
mode = "ia";
}
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) {

View file

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

View file

@ -157,22 +157,26 @@ bool ArmTranslatorVisitor::UndefinedInstruction() {
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) {
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:
imm5 = imm5 ? imm5 : 32;
return ir.LogicalShiftRight(value, ir.Imm8(imm5), carry_in);
imm5_value = imm5_value ? imm5_value : 32;
return ir.LogicalShiftRight(value, ir.Imm8(imm5_value), carry_in);
case ShiftType::ASR:
imm5 = imm5 ? imm5 : 32;
return ir.ArithmeticShiftRight(value, ir.Imm8(imm5), carry_in);
imm5_value = imm5_value ? imm5_value : 32;
return ir.ArithmeticShiftRight(value, ir.Imm8(imm5_value), carry_in);
case ShiftType::ROR:
if (imm5)
return ir.RotateRight(value, ir.Imm8(imm5), carry_in);
else
if (imm5_value) {
return ir.RotateRight(value, ir.Imm8(imm5_value), carry_in);
} else {
return ir.RotateRightExtended(value, carry_in);
}
}
UNREACHABLE();
return {};
}

View file

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

View file

@ -11,19 +11,19 @@
namespace Dynarmic::A32 {
// B <label>
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) {
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm<24> imm24) {
if (!ConditionPassed(cond)) {
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);
ir.SetTerm(IR::Term::LinkBlock{new_location});
return false;
}
// BL <label>
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm<24> imm24) {
if (!ConditionPassed(cond)) {
return true;
}
@ -31,18 +31,18 @@ bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
ir.PushRSB(ir.current_location.AdvancePC(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);
ir.SetTerm(IR::Term::LinkBlock{new_location});
return false;
}
// 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.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);
ir.SetTerm(IR::Term::LinkBlock{new_location});
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>], <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) {
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;
if (two || ConditionPassed(cond)) {
const u32 imm32 = static_cast<u8>(imm8) << 2;
const u32 imm32 = imm8.ZeroExtend() << 2;
const bool index = p;
const bool add = u;
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 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;
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) {
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>], <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) {
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;
if (two || ConditionPassed(cond)) {
const u32 imm32 = static_cast<u8>(imm8) << 2;
const u32 imm32 = imm8.ZeroExtend() << 2;
const bool index = p;
const bool add = u;
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 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;
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) {
ir.SetRegister(n, offset_address);
}

View file

@ -9,7 +9,7 @@
namespace Dynarmic::A32 {
// 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)) {
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>}
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
return true;
}
@ -363,7 +363,7 @@ bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
}
// 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)) {
return true;
}
@ -401,7 +401,7 @@ bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
}
// 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)) {
return true;
}
@ -417,7 +417,7 @@ bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
}
// 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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
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>
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
return true;
}
@ -904,7 +904,7 @@ bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rota
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
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>}
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)) {
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>
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)) {
return true;
}
@ -1146,7 +1146,7 @@ bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
}
// 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)) {
return true;
}
@ -1183,7 +1183,7 @@ bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
}
// 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)) {
return true;
}
@ -1198,7 +1198,7 @@ bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
}
// 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)) {
return true;
}

View file

@ -11,7 +11,7 @@
namespace Dynarmic::A32 {
// 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) {
return UnpredictableInstruction();
}
@ -27,12 +27,12 @@ bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm12 /*imm12*/, Imm4 /*imm4*/) {
}
// SVC<c> #<imm24>
bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) {
bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm<24> imm24) {
if (!ConditionPassed(cond)) {
return true;
}
const u32 imm32 = imm24;
const u32 imm32 = imm24.ZeroExtend();
ir.PushRSB(ir.current_location.AdvancePC(4));
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
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>]
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)) {
return true;
}
const bool add = U;
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));
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>
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) {
return UnpredictableInstruction();
}
@ -92,7 +92,7 @@ bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n,
return true;
}
const u32 imm32 = imm12;
const u32 imm32 = imm12.ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset);
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>
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");
if (m == Reg::PC) {
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>]
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) {
return UnpredictableInstruction();
}
@ -153,7 +153,7 @@ bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
return true;
}
const u32 imm32 = imm12;
const u32 imm32 = imm12.ZeroExtend();
const bool add = U;
const u32 base = ir.AlignPC(4);
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>
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) {
return UnpredictableInstruction();
}
@ -183,7 +183,7 @@ bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n
return true;
}
const u32 imm32 = imm12;
const u32 imm32 = imm12.ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset);
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>
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");
if (t == Reg::PC || m == Reg::PC) {
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>]
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) {
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 u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U;
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>
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) {
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 u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32);
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>]
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");
if (P == W) {
return UnpredictableInstruction();
@ -335,7 +335,7 @@ bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t
return true;
}
const u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U;
const u32 base = ir.AlignPC(4);
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>
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) {
return UnpredictableInstruction();
}
@ -365,7 +365,7 @@ bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n
return true;
}
const u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset);
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>]
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) {
return UnpredictableInstruction();
}
@ -408,7 +408,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
return true;
}
const u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U;
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>
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) {
return UnpredictableInstruction();
}
@ -439,7 +439,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg
return true;
}
const u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset);
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>]
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) {
return UnpredictableInstruction();
}
@ -482,7 +482,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
return true;
}
const u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const bool add = U;
const u32 base = ir.AlignPC(4);
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>
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) {
return UnpredictableInstruction();
}
@ -512,7 +512,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg
return true;
}
const u32 imm32 = (imm8a << 4) | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset);
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>
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)) {
return UnpredictableInstruction();
}
@ -556,7 +556,7 @@ bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n,
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);
ir.WriteMemory32(address, ir.GetRegister(t));
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>
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) {
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>
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) {
return UnpredictableInstruction();
}
@ -598,7 +598,7 @@ bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n
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);
ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)));
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>
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) {
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>
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) {
return UnpredictableInstruction();
}
@ -649,7 +649,7 @@ bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n
return true;
}
const u32 imm32 = imm8a << 4 | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address_a = GetAddress(ir, P, U, W, n, offset);
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>
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) {
return UnpredictableInstruction();
}
@ -711,7 +711,7 @@ bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n
return true;
}
const u32 imm32 = imm8a << 4 | imm8b;
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
const auto offset = ir.Imm32(imm32);
const auto address = GetAddress(ir, P, U, W, n, offset);

View file

@ -10,7 +10,7 @@
namespace Dynarmic::A32 {
// 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) {
return UnpredictableInstruction();
}
@ -22,7 +22,9 @@ bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
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 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>
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) {
return UnpredictableInstruction();
}
@ -43,10 +45,12 @@ bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n)
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 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);
ir.SetRegister(d, result);
@ -68,7 +72,7 @@ bool ArmTranslatorVisitor::arm_CLZ(Cond cond, Reg d, Reg m) {
}
// 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) {
return UnpredictableInstruction();
}
@ -77,7 +81,7 @@ bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
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 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>
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) {
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>()) {
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>();
const u8 width = widthm1 + 1;
const u8 left_shift_amount = static_cast<u8>(max_width - width - lsb);
const u32 width = widthm1_value + 1;
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 IR::U32 operand = ir.GetRegister(n);
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>
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) {
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>()) {
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 mask = ir.Imm32(Common::Ones<u32>(widthm1 + 1));
const IR::U32 result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(lsb)), mask);
const IR::U32 mask = ir.Imm32(Common::Ones<u32>(widthm1_value + 1));
const IR::U32 result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(u8(lsb_value))), mask);
ir.SetRegister(d, result);
return true;

View file

@ -9,7 +9,7 @@
namespace Dynarmic::A32 {
// 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) {
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>}
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) {
return UnpredictableInstruction();
}

View file

@ -19,7 +19,7 @@ static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
// Saturation instructions
// 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) {
return UnpredictableInstruction();
}
@ -28,7 +28,7 @@ bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
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 operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
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>
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) {
return UnpredictableInstruction();
}
@ -48,7 +48,7 @@ bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
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 hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
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>}
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) {
return UnpredictableInstruction();
}
@ -70,7 +70,7 @@ bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
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 operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
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>
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) {
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.
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 hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
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>
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");
if (!ConditionPassed(cond)) {

View file

@ -7,6 +7,7 @@
#pragma once
#include "common/bit_util.h"
#include "frontend/imm.h"
#include "frontend/A32/ir_emitter.h"
#include "frontend/A32/location_descriptor.h"
#include "frontend/A32/translate/translate.h"
@ -40,8 +41,8 @@ struct ArmTranslatorVisitor final {
bool UnpredictableInstruction();
bool UndefinedInstruction();
static u32 ArmExpandImm(int rotate, Imm8 imm8) {
return Common::RotateRight<u32>(imm8, rotate * 2);
static u32 ArmExpandImm(int rotate, Imm<8> imm8) {
return Common::RotateRight<u32>(imm8.ZeroExtend(), rotate * 2);
}
struct ImmAndCarry {
@ -49,96 +50,96 @@ struct ArmTranslatorVisitor final {
IR::U1 carry;
};
ImmAndCarry ArmExpandImm_C(int rotate, u32 imm8, IR::U1 carry_in) {
u32 imm32 = imm8;
ImmAndCarry ArmExpandImm_C(int rotate, Imm<8> imm8, IR::U1 carry_in) {
u32 imm32 = imm8.ZeroExtend();
auto carry_out = carry_in;
if (rotate) {
imm32 = ArmExpandImm(rotate, static_cast<Imm8>(imm8));
imm32 = ArmExpandImm(rotate, imm8);
carry_out = ir.Imm1(Common::Bit<31>(imm32));
}
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);
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);
// Barrier instructions
bool arm_DMB(Imm4 option);
bool arm_DSB(Imm4 option);
bool arm_ISB(Imm4 option);
bool arm_DMB(Imm<4> option);
bool arm_DSB(Imm<4> option);
bool arm_ISB(Imm<4> option);
// Branch instructions
bool arm_B(Cond cond, Imm24 imm24);
bool arm_BL(Cond cond, Imm24 imm24);
bool arm_BLX_imm(bool H, Imm24 imm24);
bool arm_B(Cond cond, Imm<24> imm24);
bool arm_BL(Cond cond, Imm<24> imm24);
bool arm_BLX_imm(bool H, Imm<24> imm24);
bool arm_BLX_reg(Cond cond, Reg m);
bool arm_BX(Cond cond, Reg m);
bool arm_BXJ(Cond cond, Reg m);
// 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_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_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_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
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
bool arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
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_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
bool arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
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_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8);
bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8);
bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
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, 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_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
bool arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
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_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
bool arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
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);
// Exception generating instructions
bool arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4);
bool arm_SVC(Cond cond, Imm24 imm24);
bool arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4);
bool arm_SVC(Cond cond, Imm<24> imm24);
bool arm_UDF();
// Extension instructions
@ -171,31 +172,31 @@ struct ArmTranslatorVisitor final {
bool arm_STRBT();
bool arm_STRHT();
bool arm_STRT();
bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12);
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 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_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12);
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 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_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
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, Imm<12> imm12);
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, Imm<12> 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, Imm<5> imm5, ShiftType shift, Reg m);
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, 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_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b);
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, 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, 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_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, 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, 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_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, 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, 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_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 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_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 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_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
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, Imm<5> imm5, ShiftType shift, Reg m);
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, Imm<5> imm5, ShiftType shift, Reg m);
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_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);
// Load/Store multiple instructions
@ -212,23 +213,23 @@ struct ArmTranslatorVisitor final {
bool arm_STM_usr();
// Miscellaneous instructions
bool arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb);
bool arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n);
bool arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb);
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_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_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_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
bool arm_USAD8(Cond cond, Reg d, Reg m, Reg n);
bool arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n);
// Packing instructions
bool arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m);
bool arm_PKHTB(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, Imm<5> imm5, Reg m);
// Reversal instructions
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);
// Saturation instructions
bool arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n);
bool arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n);
bool arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n);
bool arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, 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, Imm<4> sat_imm, Reg d, 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, Imm<4> sat_imm, Reg d, Reg n);
// Divide instructions
bool arm_SDIV(Cond cond, Reg d, Reg m, Reg n);
@ -343,7 +344,7 @@ struct ArmTranslatorVisitor final {
// Status register access instructions
bool arm_CPS();
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_RFE();
bool arm_SETEND(bool E);
@ -387,14 +388,14 @@ struct ArmTranslatorVisitor final {
bool vfp2_VMRS(Cond cond, Reg t);
// 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_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8);
bool vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8);
bool vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 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_a2(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, Imm8 imm8);
bool vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, 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, Imm<8> 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, Imm<8> 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, Imm<8> 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, Imm<8> imm8);
};
} // namespace Dynarmic::A32

View file

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

View file

@ -39,14 +39,6 @@ enum class ExtReg {
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;
enum class ShiftType {