A32: Replace immediate type aliases with the Imm template
Replaces type aliases of raw integral types with the more type-safe Imm template, like how the AArch64 frontend has been using it. This makes the two frontends more consistent with one another.
This commit is contained in:
parent
f96036b3f1
commit
4ba2318b2e
17 changed files with 765 additions and 541 deletions
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
#include "frontend/imm.h"
|
||||||
#include "frontend/A32/decoder/arm.h"
|
#include "frontend/A32/decoder/arm.h"
|
||||||
#include "frontend/A32/decoder/vfp2.h"
|
#include "frontend/A32/decoder/vfp2.h"
|
||||||
#include "frontend/A32/disassembler/disassembler.h"
|
#include "frontend/A32/disassembler/disassembler.h"
|
||||||
|
@ -23,24 +24,24 @@ class DisassemblerVisitor {
|
||||||
public:
|
public:
|
||||||
using instruction_return_type = std::string;
|
using instruction_return_type = std::string;
|
||||||
|
|
||||||
static u32 ArmExpandImm(int rotate, Imm8 imm8) {
|
static u32 ArmExpandImm(int rotate, Imm<8> imm8) {
|
||||||
return Common::RotateRight(static_cast<u32>(imm8), rotate*2);
|
return Common::RotateRight(static_cast<u32>(imm8.ZeroExtend()), rotate*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string ShiftStr(ShiftType shift, Imm5 imm5) {
|
static std::string ShiftStr(ShiftType shift, Imm<5> imm5) {
|
||||||
switch (shift) {
|
switch (shift) {
|
||||||
case ShiftType::LSL:
|
case ShiftType::LSL:
|
||||||
if (imm5 == 0) return "";
|
if (imm5 == 0) return "";
|
||||||
return fmt::format(", lsl #{}", imm5);
|
return fmt::format(", lsl #{}", imm5.ZeroExtend());
|
||||||
case ShiftType::LSR:
|
case ShiftType::LSR:
|
||||||
if (imm5 == 0) return ", lsr #32";
|
if (imm5 == 0) return ", lsr #32";
|
||||||
return fmt::format(", lsr #{}", imm5);
|
return fmt::format(", lsr #{}", imm5.ZeroExtend());
|
||||||
case ShiftType::ASR:
|
case ShiftType::ASR:
|
||||||
if (imm5 == 0) return ", asr #32";
|
if (imm5 == 0) return ", asr #32";
|
||||||
return fmt::format(", asr #{}", imm5);
|
return fmt::format(", asr #{}", imm5.ZeroExtend());
|
||||||
case ShiftType::ROR:
|
case ShiftType::ROR:
|
||||||
if (imm5 == 0) return ", rrx";
|
if (imm5 == 0) return ", rrx";
|
||||||
return fmt::format(", ror #{}", imm5);
|
return fmt::format(", ror #{}", imm5.ZeroExtend());
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return "<internal error>";
|
return "<internal error>";
|
||||||
|
@ -76,8 +77,8 @@ public:
|
||||||
return "<internal error>";
|
return "<internal error>";
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* BarrierOptionStr(Imm4 option) {
|
static const char* BarrierOptionStr(Imm<4> option) {
|
||||||
switch (option) {
|
switch (option.ZeroExtend()) {
|
||||||
case 0b0010:
|
case 0b0010:
|
||||||
return " oshst";
|
return " oshst";
|
||||||
case 0b0011:
|
case 0b0011:
|
||||||
|
@ -124,27 +125,27 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Barrier instructions
|
// Barrier instructions
|
||||||
std::string arm_DMB(Imm4 option) {
|
std::string arm_DMB(Imm<4> option) {
|
||||||
return fmt::format("dmb{}", BarrierOptionStr(option));
|
return fmt::format("dmb{}", BarrierOptionStr(option));
|
||||||
}
|
}
|
||||||
std::string arm_DSB(Imm4 option) {
|
std::string arm_DSB(Imm<4> option) {
|
||||||
return fmt::format("dsb{}", BarrierOptionStr(option));
|
return fmt::format("dsb{}", BarrierOptionStr(option));
|
||||||
}
|
}
|
||||||
std::string arm_ISB([[maybe_unused]] Imm4 option) {
|
std::string arm_ISB([[maybe_unused]] Imm<4> option) {
|
||||||
return "isb";
|
return "isb";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
std::string arm_B(Cond cond, Imm24 imm24) {
|
std::string arm_B(Cond cond, Imm<24> imm24) {
|
||||||
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
|
const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8;
|
||||||
return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
|
return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
|
||||||
}
|
}
|
||||||
std::string arm_BL(Cond cond, Imm24 imm24) {
|
std::string arm_BL(Cond cond, Imm<24> imm24) {
|
||||||
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
|
const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8;
|
||||||
return fmt::format("bl{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
|
return fmt::format("bl{} {}#{}", CondToString(cond), Common::SignToChar(offset), abs(offset));
|
||||||
}
|
}
|
||||||
std::string arm_BLX_imm(bool H, Imm24 imm24) {
|
std::string arm_BLX_imm(bool H, Imm<24> imm24) {
|
||||||
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8 + (H ? 2 : 0);
|
const s32 offset = Common::SignExtend<26, s32>(imm24.ZeroExtend() << 2) + 8 + (H ? 2 : 0);
|
||||||
return fmt::format("blx {}#{}", Common::SignToChar(offset), abs(offset));
|
return fmt::format("blx {}#{}", Common::SignToChar(offset), abs(offset));
|
||||||
}
|
}
|
||||||
std::string arm_BLX_reg(Cond cond, Reg m) {
|
std::string arm_BLX_reg(Cond cond, Reg m) {
|
||||||
|
@ -162,16 +163,24 @@ public:
|
||||||
return fmt::format("cdp{} p{}, #{}, {}, {}, {}, #{}", CondToString(cond), coproc_no, opc1, CRd, CRn, CRm, opc2);
|
return fmt::format("cdp{} p{}, #{}, {}, {}, {}, #{}", CondToString(cond), coproc_no, opc1, CRd, CRn, CRm, opc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
std::string arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
|
||||||
const u32 imm32 = static_cast<u32>(imm8) << 2;
|
const u32 imm32 = static_cast<u32>(imm8.ZeroExtend()) << 2;
|
||||||
if (!p && !u && !d && !w)
|
if (!p && !u && !d && !w) {
|
||||||
return "<undefined>";
|
return "<undefined>";
|
||||||
if (p)
|
}
|
||||||
return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : "");
|
if (p) {
|
||||||
if (!p && w)
|
return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "",
|
||||||
return fmt::format("ldc{}{} {}, {}, [{}], #{}{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32);
|
CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32,
|
||||||
if (!p && !w && u)
|
w ? "!" : "");
|
||||||
return fmt::format("ldc{}{} {}, {}, [{}], {}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, imm8);
|
}
|
||||||
|
if (!p && w) {
|
||||||
|
return fmt::format("ldc{}{} {}, {}, [{}], #{}{}", d ? "l" : "",
|
||||||
|
CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32);
|
||||||
|
}
|
||||||
|
if (!p && !w && u) {
|
||||||
|
return fmt::format("ldc{}{} {}, {}, [{}], {}", d ? "l" : "",
|
||||||
|
CondOrTwo(cond), coproc_no, CRd, n, imm8.ZeroExtend());
|
||||||
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return "<internal error>";
|
return "<internal error>";
|
||||||
}
|
}
|
||||||
|
@ -192,160 +201,169 @@ public:
|
||||||
return fmt::format("mrrc{} p{}, #{}, {}, {}, {}", CondOrTwo(cond), coproc_no, opc, t, t2, CRm);
|
return fmt::format("mrrc{} p{}, #{}, {}, {}, {}", CondOrTwo(cond), coproc_no, opc, t, t2, CRm);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
std::string arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
|
||||||
const u32 imm32 = static_cast<u32>(imm8) << 2;
|
const u32 imm32 = static_cast<u32>(imm8.ZeroExtend()) << 2;
|
||||||
if (!p && !u && !d && !w)
|
if (!p && !u && !d && !w) {
|
||||||
return "<undefined>";
|
return "<undefined>";
|
||||||
if (p)
|
}
|
||||||
return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : "");
|
if (p) {
|
||||||
if (!p && w)
|
return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "",
|
||||||
return fmt::format("stc{}{} {}, {}, [{}], #{}{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32);
|
CondOrTwo(cond), coproc_no, CRd, n,
|
||||||
if (!p && !w && u)
|
u ? "+" : "-", imm32, w ? "!" : "");
|
||||||
return fmt::format("stc{}{} {}, {}, [{}], {}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, imm8);
|
}
|
||||||
|
if (!p && w) {
|
||||||
|
return fmt::format("stc{}{} {}, {}, [{}], #{}{}", d ? "l" : "",
|
||||||
|
CondOrTwo(cond), coproc_no, CRd, n,
|
||||||
|
u ? "+" : "-", imm32);
|
||||||
|
}
|
||||||
|
if (!p && !w && u) {
|
||||||
|
return fmt::format("stc{}{} {}, {}, [{}], {}", d ? "l" : "",
|
||||||
|
CondOrTwo(cond), coproc_no, CRd, n, imm8.ZeroExtend());
|
||||||
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return "<internal error>";
|
return "<internal error>";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data processing instructions
|
// Data processing instructions
|
||||||
std::string arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("adc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("adc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("adc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("adc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("adc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("adc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("add{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("add{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("add{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("add{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("add{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("add{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("and{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("and{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("and{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("and{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("and{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("and{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("bic{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("bic{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("bic{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("bic{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("bic{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("bic{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
std::string arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("cmn{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
return fmt::format("cmn{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("cmn{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
return fmt::format("cmn{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
std::string arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("cmn{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
|
return fmt::format("cmn{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
std::string arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("cmp{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
return fmt::format("cmp{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("cmp{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
return fmt::format("cmp{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
std::string arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("cmp{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
|
return fmt::format("cmp{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("eor{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("eor{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("eor{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("eor{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("eor{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("eor{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("mov{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8));
|
return fmt::format("mov{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("mov{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5));
|
return fmt::format("mov{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("mov{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m));
|
return fmt::format("mov{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("mvn{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8));
|
return fmt::format("mvn{}{} {}, #{}", CondToString(cond), S ? "s" : "", d, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("mvn{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5));
|
return fmt::format("mvn{}{} {}, {}{}", CondToString(cond), S ? "s" : "", d, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("mvn{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m));
|
return fmt::format("mvn{}{} {}, {}", CondToString(cond), S ? "s" : "", d, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("orr{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("orr{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("orr{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("orr{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("orr{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("orr{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("rsb{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("rsb{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("rsb{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("rsb{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("rsb{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("rsb{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("rsc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("rsc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("rsc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("rsc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("rsc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("rsc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("sbc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("sbc{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("sbc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("sbc{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("sbc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("sbc{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("sub{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
return fmt::format("sub{}{} {}, {}, #{}", CondToString(cond), S ? "s" : "", d, n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("sub{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
return fmt::format("sub{}{} {}, {}, {}{}", CondToString(cond), S ? "s" : "", d, n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
std::string arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("sub{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
return fmt::format("sub{}{} {}, {}, {}", CondToString(cond), S ? "s" : "", d, n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
std::string arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("teq{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
return fmt::format("teq{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("teq{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
return fmt::format("teq{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
std::string arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return fmt::format("teq{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
|
return fmt::format("teq{} {}, {}", CondToString(cond), n, RsrStr(s, shift, m));
|
||||||
}
|
}
|
||||||
std::string arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
std::string arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
return fmt::format("tst{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
return fmt::format("tst{} {}, #{}", CondToString(cond), n, ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
return fmt::format("tst{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
return fmt::format("tst{} {}, {}{}", CondToString(cond), n, m, ShiftStr(shift, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
std::string arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
|
@ -353,11 +371,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exception generation instructions
|
// Exception generation instructions
|
||||||
std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) {
|
std::string arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4) {
|
||||||
return fmt::format("bkpt{} #{}", CondToString(cond), imm12 << 4 | imm4);
|
return fmt::format("bkpt{} #{}", CondToString(cond), concatenate(imm12, imm4).ZeroExtend());
|
||||||
}
|
}
|
||||||
std::string arm_SVC(Cond cond, Imm24 imm24) {
|
std::string arm_SVC(Cond cond, Imm<24> imm24) {
|
||||||
return fmt::format("svc{} #{}", CondToString(cond), imm24);
|
return fmt::format("svc{} #{}", CondToString(cond), imm24.ZeroExtend());
|
||||||
}
|
}
|
||||||
std::string arm_UDF() {
|
std::string arm_UDF() {
|
||||||
return fmt::format("udf");
|
return fmt::format("udf");
|
||||||
|
@ -409,179 +427,307 @@ public:
|
||||||
std::string arm_YIELD() { return "yield <unimplemented>"; }
|
std::string arm_YIELD() { return "yield <unimplemented>"; }
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
std::string arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
std::string arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
|
||||||
bool P = true, W = false;
|
bool P = true, W = false;
|
||||||
return arm_LDR_imm(cond, P, U, W, Reg::PC, t, imm12);
|
return arm_LDR_imm(cond, P, U, W, Reg::PC, t, imm12);
|
||||||
}
|
}
|
||||||
std::string arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
std::string arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
|
const u32 imm12_value = imm12.ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldr{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
|
return fmt::format("ldr{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign,
|
||||||
|
imm12_value, W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldr{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldr{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign,
|
||||||
|
imm12_value, W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldr{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : "");
|
return fmt::format("ldr{} {}, [{}, {}{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldr{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldr{} {}, [{}], {}{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
std::string arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
|
||||||
bool P = true, W = false;
|
const bool P = true;
|
||||||
|
const bool W = false;
|
||||||
return arm_LDRB_imm(cond, P, U, W, Reg::PC, t, imm12);
|
return arm_LDRB_imm(cond, P, U, W, Reg::PC, t, imm12);
|
||||||
}
|
}
|
||||||
std::string arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
std::string arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
|
const u32 imm12_value = imm12.ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
|
return fmt::format("ldrb{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm12_value,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrb{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrb{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm12_value,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrb{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : "");
|
return fmt::format("ldrb{} {}, [{}, {}{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrb{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrb{} {}, [{}], {}{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRBT() { return "ice"; }
|
std::string arm_LDRBT() { return "ice"; }
|
||||||
std::string arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
bool P = true, W = false;
|
const bool P = true;
|
||||||
|
const bool W = false;
|
||||||
return arm_LDRD_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
return arm_LDRD_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
}
|
}
|
||||||
std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrd{} {}, {}, [{}, #{}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? "!" : "");
|
return fmt::format("ldrd{} {}, {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, imm32,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrd{} {}, {}, [{}], #{}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrd{} {}, {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, imm32,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
std::string arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrd{} {}, {}, [{}, {}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? "!" : "");
|
return fmt::format("ldrd{} {}, {}, [{}, {}{}]{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, m,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrd{} {}, {}, [{}], {}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrd{} {}, {}, [{}], {}{}{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, m,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
return arm_LDRH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
return arm_LDRH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
}
|
}
|
||||||
std::string arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrh{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : "");
|
return fmt::format("ldrh{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrh{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrh{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
std::string arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrh{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : "");
|
return fmt::format("ldrh{} {}, [{}, {}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrh{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrh{} {}, [{}], {}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRHT() { return "ice"; }
|
std::string arm_LDRHT() { return "ice"; }
|
||||||
std::string arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
bool P = true, W = false;
|
const bool P = true;
|
||||||
|
const bool W = false;
|
||||||
return arm_LDRSB_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
return arm_LDRSB_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
}
|
}
|
||||||
std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrsb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : "");
|
return fmt::format("ldrsb{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrsb{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrsb{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
std::string arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrsb{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : "");
|
return fmt::format("ldrsb{} {}, [{}, {}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrsb{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrsb{} {}, [{}], {}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRSBT() { return "ice"; }
|
std::string arm_LDRSBT() { return "ice"; }
|
||||||
std::string arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
bool P = true, W = false;
|
const bool P = true;
|
||||||
|
const bool W = false;
|
||||||
return arm_LDRSH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
return arm_LDRSH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
}
|
}
|
||||||
std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrsh{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : "");
|
return fmt::format("ldrsh{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrsh{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrsh{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
std::string arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("ldrsh{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : "");
|
return fmt::format("ldrsh{} {}, [{}, {}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("ldrsh{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("ldrsh{} {}, [{}], {}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_LDRSHT() { return "ice"; }
|
std::string arm_LDRSHT() { return "ice"; }
|
||||||
std::string arm_LDRT() { return "ice"; }
|
std::string arm_LDRT() { return "ice"; }
|
||||||
std::string arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
std::string arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
|
const u32 imm12_value = imm12.ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("str{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
|
return fmt::format("str{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm12_value,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("str{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("str{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm12_value,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("str{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : "");
|
return fmt::format("str{} {}, [{}, {}{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("str{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
return fmt::format("str{} {}, [{}], {}{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
std::string arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
|
const u32 imm12_value = imm12.ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("strb{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? "!" : "");
|
return fmt::format("strb{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm12_value,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("strb{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm12, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("strb{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm12_value,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
std::string arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("strb{} {}, [{}, {}{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? "!" : "");
|
return fmt::format("strb{} {}, [{}, {}{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("strb{} {}, [{}], {}{}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
return fmt::format("strb{} {}, [{}], {}{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
ShiftStr(shift, imm5), W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRBT() { return "ice"; }
|
std::string arm_STRBT() { return "ice"; }
|
||||||
std::string arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("strd{} {}, {}, [{}, #{}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? "!" : "");
|
return fmt::format("strd{} {}, {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, imm32,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("strd{} {}, {}, [{}], #{}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("strd{} {}, {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, imm32,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
std::string arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("strd{} {}, {}, [{}, {}{}]{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? "!" : "");
|
return fmt::format("strd{} {}, {}, [{}, {}{}]{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, m,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("strd{} {}, {}, [{}], {}{}{}", CondToString(cond), t, t+1, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("strd{} {}, {}, [{}], {}{}{}",
|
||||||
|
CondToString(cond), t, t+1, n, sign, m,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("strh{} {}, [{}, #{}{}]{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? "!" : "");
|
return fmt::format("strh{} {}, [{}, #{}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("strh{} {}, [{}], #{}{}{}", CondToString(cond), t, n, U ? '+' : '-', imm32, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("strh{} {}, [{}], #{}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, imm32,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
std::string arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
const char sign = U ? '+' : '-';
|
||||||
|
|
||||||
if (P) {
|
if (P) {
|
||||||
return fmt::format("strd{} {}, [{}, {}{}]{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? "!" : "");
|
return fmt::format("strd{} {}, [{}, {}{}]{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? "!" : "");
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("strd{} {}, [{}], {}{}{}", CondToString(cond), t, n, U ? '+' : '-', m, W ? " (err: W == 1!!!)" : "");
|
return fmt::format("strd{} {}, [{}], {}{}{}",
|
||||||
|
CondToString(cond), t, n, sign, m,
|
||||||
|
W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string arm_STRHT() { return "ice"; }
|
std::string arm_STRHT() { return "ice"; }
|
||||||
|
@ -617,17 +763,24 @@ public:
|
||||||
std::string arm_STM_usr() { return "ice"; }
|
std::string arm_STM_usr() { return "ice"; }
|
||||||
|
|
||||||
// Miscellaneous instructions
|
// Miscellaneous instructions
|
||||||
std::string arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
|
std::string arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb) {
|
||||||
return fmt::format("bfc{} {}, #{}, #{}", CondToString(cond), d, lsb, msb - lsb + 1);
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 width = msb.ZeroExtend() - lsb_value + 1;
|
||||||
|
return fmt::format("bfc{} {}, #{}, #{}",
|
||||||
|
CondToString(cond), d, lsb_value, width);
|
||||||
}
|
}
|
||||||
std::string arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n) {
|
std::string arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n) {
|
||||||
return fmt::format("bfi{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, msb - lsb + 1);
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 width = msb.ZeroExtend() - lsb_value + 1;
|
||||||
|
return fmt::format("bfi{} {}, {}, #{}, #{}",
|
||||||
|
CondToString(cond), d, n, lsb_value, width);
|
||||||
}
|
}
|
||||||
std::string arm_CLZ(Cond cond, Reg d, Reg m) {
|
std::string arm_CLZ(Cond cond, Reg d, Reg m) {
|
||||||
return fmt::format("clz{} {}, {}", CondToString(cond), d, m);
|
return fmt::format("clz{} {}, {}", CondToString(cond), d, m);
|
||||||
}
|
}
|
||||||
std::string arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
|
std::string arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12) {
|
||||||
return fmt::format("movt{} {}, #{}", CondToString(cond), d, (imm4 << 12) | imm12);
|
const u32 imm = concatenate(imm4, imm12).ZeroExtend();
|
||||||
|
return fmt::format("movt{} {}, #{}", CondToString(cond), d, imm);
|
||||||
}
|
}
|
||||||
std::string arm_NOP() {
|
std::string arm_NOP() {
|
||||||
return "nop";
|
return "nop";
|
||||||
|
@ -635,14 +788,20 @@ public:
|
||||||
std::string arm_RBIT(Cond cond, Reg d, Reg m) {
|
std::string arm_RBIT(Cond cond, Reg d, Reg m) {
|
||||||
return fmt::format("rbit{} {}, {}", CondToString(cond), d, m);
|
return fmt::format("rbit{} {}, {}", CondToString(cond), d, m);
|
||||||
}
|
}
|
||||||
std::string arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) {
|
std::string arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
|
||||||
return fmt::format("sbfx{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, widthm1 + 1);
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 width = widthm1.ZeroExtend() + 1;
|
||||||
|
return fmt::format("sbfx{} {}, {}, #{}, #{}",
|
||||||
|
CondToString(cond), d, n, lsb_value, width);
|
||||||
}
|
}
|
||||||
std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) {
|
std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return fmt::format("sel{} {}, {}, {}", CondToString(cond), d, n, m);
|
return fmt::format("sel{} {}, {}, {}", CondToString(cond), d, n, m);
|
||||||
}
|
}
|
||||||
std::string arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) {
|
std::string arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
|
||||||
return fmt::format("ubfx{} {}, {}, #{}, #{}", CondToString(cond), d, n, lsb, widthm1 + 1);
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 width = widthm1.ZeroExtend() + 1;
|
||||||
|
return fmt::format("ubfx{} {}, {}, #{}, #{}",
|
||||||
|
CondToString(cond), d, n, lsb_value, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsigned sum of absolute difference functions
|
// Unsigned sum of absolute difference functions
|
||||||
|
@ -654,10 +813,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packing instructions
|
// Packing instructions
|
||||||
std::string arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) {
|
std::string arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
|
||||||
return fmt::format("pkhbt{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::LSL, imm5));
|
return fmt::format("pkhbt{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::LSL, imm5));
|
||||||
}
|
}
|
||||||
std::string arm_PKHTB(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) {
|
std::string arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
|
||||||
return fmt::format("pkhtb{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::ASR, imm5));
|
return fmt::format("pkhtb{} {}, {}, {}{}", CondToString(cond), d, n, m, ShiftStr(ShiftType::ASR, imm5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,17 +832,25 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saturation instructions
|
// Saturation instructions
|
||||||
std::string arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) {
|
std::string arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
|
||||||
return fmt::format("ssat{} {}, #{}, {}{}", CondToString(cond), d, sat_imm + 1, n, ShiftStr(ShiftType(sh << 1), imm5));
|
const u32 bit_position = sat_imm.ZeroExtend() + 1;
|
||||||
|
return fmt::format("ssat{} {}, #{}, {}{}",
|
||||||
|
CondToString(cond), d, bit_position, n,
|
||||||
|
ShiftStr(ShiftType(sh << 1), imm5));
|
||||||
}
|
}
|
||||||
std::string arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
std::string arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
|
||||||
return fmt::format("ssat16{} {}, #{}, {}", CondToString(cond), d, sat_imm + 1, n);
|
const u32 bit_position = sat_imm.ZeroExtend() + 1;
|
||||||
|
return fmt::format("ssat16{} {}, #{}, {}",
|
||||||
|
CondToString(cond), d, bit_position, n);
|
||||||
}
|
}
|
||||||
std::string arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) {
|
std::string arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
|
||||||
return fmt::format("usat{} {}, #{}, {}{}", CondToString(cond), d, sat_imm, n, ShiftStr(ShiftType(sh << 1), imm5));
|
return fmt::format("usat{} {}, #{}, {}{}",
|
||||||
|
CondToString(cond), d, sat_imm.ZeroExtend(), n,
|
||||||
|
ShiftStr(ShiftType(sh << 1), imm5));
|
||||||
}
|
}
|
||||||
std::string arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
std::string arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
|
||||||
return fmt::format("usat16{} {}, #{}, {}", CondToString(cond), d, sat_imm, n);
|
return fmt::format("usat16{} {}, #{}, {}",
|
||||||
|
CondToString(cond), d, sat_imm.ZeroExtend(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Divide instructions
|
// Divide instructions
|
||||||
|
@ -940,19 +1107,31 @@ public:
|
||||||
std::string arm_MRS(Cond cond, Reg d) {
|
std::string arm_MRS(Cond cond, Reg d) {
|
||||||
return fmt::format("mrs{} {}, apsr", CondToString(cond), d);
|
return fmt::format("mrs{} {}, apsr", CondToString(cond), d);
|
||||||
}
|
}
|
||||||
std::string arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8) {
|
std::string arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8) {
|
||||||
const bool write_c = Common::Bit<0>(mask);
|
const bool write_c = Common::Bit<0>(mask);
|
||||||
const bool write_x = Common::Bit<1>(mask);
|
const bool write_x = Common::Bit<1>(mask);
|
||||||
const bool write_s = Common::Bit<2>(mask);
|
const bool write_s = Common::Bit<2>(mask);
|
||||||
const bool write_f = Common::Bit<3>(mask);
|
const bool write_f = Common::Bit<3>(mask);
|
||||||
return fmt::format("msr{} cpsr_{}{}{}{}, #{}", CondToString(cond), write_c ? "c" : "", write_x ? "x" : "", write_s ? "s" : "", write_f ? "f" : "", ArmExpandImm(rotate, imm8));
|
return fmt::format("msr{} cpsr_{}{}{}{}, #{}",
|
||||||
|
CondToString(cond),
|
||||||
|
write_c ? "c" : "",
|
||||||
|
write_x ? "x" : "",
|
||||||
|
write_s ? "s" : "",
|
||||||
|
write_f ? "f" : "",
|
||||||
|
ArmExpandImm(rotate, imm8));
|
||||||
}
|
}
|
||||||
std::string arm_MSR_reg(Cond cond, int mask, Reg n) {
|
std::string arm_MSR_reg(Cond cond, int mask, Reg n) {
|
||||||
const bool write_c = Common::Bit<0>(mask);
|
const bool write_c = Common::Bit<0>(mask);
|
||||||
const bool write_x = Common::Bit<1>(mask);
|
const bool write_x = Common::Bit<1>(mask);
|
||||||
const bool write_s = Common::Bit<2>(mask);
|
const bool write_s = Common::Bit<2>(mask);
|
||||||
const bool write_f = Common::Bit<3>(mask);
|
const bool write_f = Common::Bit<3>(mask);
|
||||||
return fmt::format("msr{} cpsr_{}{}{}{}, {}", CondToString(cond), write_c ? "c" : "", write_x ? "x" : "", write_s ? "s" : "", write_f ? "f" : "", n);
|
return fmt::format("msr{} cpsr_{}{}{}{}, {}",
|
||||||
|
CondToString(cond),
|
||||||
|
write_c ? "c" : "",
|
||||||
|
write_x ? "x" : "",
|
||||||
|
write_s ? "s" : "",
|
||||||
|
write_f ? "f" : "",
|
||||||
|
n);
|
||||||
}
|
}
|
||||||
std::string arm_RFE() { return "ice"; }
|
std::string arm_RFE() { return "ice"; }
|
||||||
std::string arm_SETEND(bool E) {
|
std::string arm_SETEND(bool E) {
|
||||||
|
@ -1080,52 +1259,83 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) {
|
std::string vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
return fmt::format("vpop{} {}(+{})", CondToString(cond), FPRegStr(sz, Vd, D), imm8 >> (sz ? 1 : 0));
|
return fmt::format("vpop{} {}(+{})",
|
||||||
|
CondToString(cond), FPRegStr(sz, Vd, D),
|
||||||
|
imm8.ZeroExtend() >> (sz ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) {
|
std::string vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
return fmt::format("vpush{} {}(+{})", CondToString(cond), FPRegStr(sz, Vd, D), imm8 >> (sz ? 1 : 0));
|
return fmt::format("vpush{} {}(+{})",
|
||||||
|
CondToString(cond), FPRegStr(sz, Vd, D),
|
||||||
|
imm8.ZeroExtend() >> (sz ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) {
|
std::string vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
return fmt::format("vldr{} {}, [{}, #{}{}]", CondToString(cond), FPRegStr(sz, Vd, D), n, U ? '+' : '-', imm32);
|
const char sign = U ? '+' : '-';
|
||||||
|
return fmt::format("vldr{} {}, [{}, #{}{}]",
|
||||||
|
CondToString(cond), FPRegStr(sz, Vd, D), n, sign, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) {
|
std::string vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
return fmt::format("vstr{} {}, [{}, #{}{}]", CondToString(cond), FPRegStr(sz, Vd, D), n, U ? '+' : '-', imm32);
|
const char sign = U ? '+' : '-';
|
||||||
|
return fmt::format("vstr{} {}, [{}, #{}{}]",
|
||||||
|
CondToString(cond), FPRegStr(sz, Vd, D), n, sign, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
std::string vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
const char* mode = "<invalid mode>";
|
const char* mode = "<invalid mode>";
|
||||||
if (!p && u) mode = "ia";
|
if (!p && u) {
|
||||||
if (p && !u) mode = "db";
|
mode = "ia";
|
||||||
return fmt::format("vstm{}{}.f64 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(true, Vd, D), imm8);
|
}
|
||||||
|
if (p && !u) {
|
||||||
|
mode = "db";
|
||||||
|
}
|
||||||
|
return fmt::format("vstm{}{}.f64 {}{}, {}(+{})", mode,
|
||||||
|
CondToString(cond), n, w ? "!" : "",
|
||||||
|
FPRegStr(true, Vd, D), imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
std::string vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
const char* mode = "<invalid mode>";
|
const char* mode = "<invalid mode>";
|
||||||
if (!p && u) mode = "ia";
|
if (!p && u) {
|
||||||
if (p && !u) mode = "db";
|
mode = "ia";
|
||||||
return fmt::format("vstm{}{}.f32 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(false, Vd, D), imm8);
|
}
|
||||||
|
if (p && !u) {
|
||||||
|
mode = "db";
|
||||||
|
}
|
||||||
|
return fmt::format("vstm{}{}.f32 {}{}, {}(+{})", mode,
|
||||||
|
CondToString(cond), n, w ? "!" : "",
|
||||||
|
FPRegStr(false, Vd, D), imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
std::string vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
const char* mode = "<invalid mode>";
|
const char* mode = "<invalid mode>";
|
||||||
if (!p && u) mode = "ia";
|
if (!p && u) {
|
||||||
if (p && !u) mode = "db";
|
mode = "ia";
|
||||||
return fmt::format("vldm{}{}.f64 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(true, Vd, D), imm8);
|
}
|
||||||
|
if (p && !u) {
|
||||||
|
mode = "db";
|
||||||
|
}
|
||||||
|
return fmt::format("vldm{}{}.f64 {}{}, {}(+{})", mode,
|
||||||
|
CondToString(cond), n, w ? "!" : "",
|
||||||
|
FPRegStr(true, Vd, D), imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
std::string vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
const char* mode = "<invalid mode>";
|
const char* mode = "<invalid mode>";
|
||||||
if (!p && u) mode = "ia";
|
if (!p && u) {
|
||||||
if (p && !u) mode = "db";
|
mode = "ia";
|
||||||
return fmt::format("vldm{}{}.f32 {}{}, {}(+{})", mode, CondToString(cond), n, w ? "!" : "", FPRegStr(false, Vd, D), imm8);
|
}
|
||||||
|
if (p && !u) {
|
||||||
|
mode = "db";
|
||||||
|
}
|
||||||
|
return fmt::format("vldm{}{}.f32 {}{}, {}(+{})", mode,
|
||||||
|
CondToString(cond), n, w ? "!" : "",
|
||||||
|
FPRegStr(false, Vd, D), imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string DisassembleArm(u32 instruction) {
|
std::string DisassembleArm(u32 instruction) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
#include "frontend/imm.h"
|
||||||
#include "frontend/A32/decoder/thumb16.h"
|
#include "frontend/A32/decoder/thumb16.h"
|
||||||
#include "frontend/A32/disassembler/disassembler.h"
|
#include "frontend/A32/disassembler/disassembler.h"
|
||||||
#include "frontend/A32/types.h"
|
#include "frontend/A32/types.h"
|
||||||
|
@ -22,16 +23,18 @@ class DisassemblerVisitor {
|
||||||
public:
|
public:
|
||||||
using instruction_return_type = std::string;
|
using instruction_return_type = std::string;
|
||||||
|
|
||||||
std::string thumb16_LSL_imm(Imm5 imm5, Reg m, Reg d) {
|
std::string thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||||
return fmt::format("lsls {}, {}, #{}", d, m, imm5);
|
return fmt::format("lsls {}, {}, #{}", d, m, imm5.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LSR_imm(Imm5 imm5, Reg m, Reg d) {
|
std::string thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||||
return fmt::format("lsrs {}, {}, #{}", d, m, imm5 != 0 ? imm5 : 32);
|
const u32 shift = imm5 != 0 ? imm5.ZeroExtend() : 32U;
|
||||||
|
return fmt::format("lsrs {}, {}, #{}", d, m, shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ASR_imm(Imm5 imm5, Reg m, Reg d) {
|
std::string thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||||
return fmt::format("asrs {}, {}, #{}", d, m, imm5 != 0 ? imm5 : 32);
|
const u32 shift = imm5 != 0 ? imm5.ZeroExtend() : 32U;
|
||||||
|
return fmt::format("asrs {}, {}, #{}", d, m, shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) {
|
std::string thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) {
|
||||||
|
@ -42,28 +45,28 @@ public:
|
||||||
return fmt::format("subs {}, {}, {}", d, n, m);
|
return fmt::format("subs {}, {}, {}", d, n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) {
|
std::string thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) {
|
||||||
return fmt::format("adds {}, {}, #{}", d, n, imm3);
|
return fmt::format("adds {}, {}, #{}", d, n, imm3.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) {
|
std::string thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d) {
|
||||||
return fmt::format("subs {}, {}, #{}", d, n, imm3);
|
return fmt::format("subs {}, {}, #{}", d, n, imm3.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_MOV_imm(Reg d, Imm8 imm8) {
|
std::string thumb16_MOV_imm(Reg d, Imm<8> imm8) {
|
||||||
return fmt::format("movs {}, #{}", d, imm8);
|
return fmt::format("movs {}, #{}", d, imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_CMP_imm(Reg n, Imm8 imm8) {
|
std::string thumb16_CMP_imm(Reg n, Imm<8> imm8) {
|
||||||
return fmt::format("cmp {}, #{}", n, imm8);
|
return fmt::format("cmp {}, #{}", n, imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADD_imm_t2(Reg d_n, Imm8 imm8) {
|
std::string thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) {
|
||||||
return fmt::format("adds {}, #{}", d_n, imm8);
|
return fmt::format("adds {}, #{}", d_n, imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_SUB_imm_t2(Reg d_n, Imm8 imm8) {
|
std::string thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8) {
|
||||||
return fmt::format("subs {}, #{}", d_n, imm8);
|
return fmt::format("subs {}, #{}", d_n, imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_AND_reg(Reg m, Reg d_n) {
|
std::string thumb16_AND_reg(Reg m, Reg d_n) {
|
||||||
|
@ -132,22 +135,22 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) {
|
std::string thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) {
|
||||||
Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;
|
const Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;
|
||||||
return fmt::format("add {}, {}", d_n, m);
|
return fmt::format("add {}, {}", d_n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) {
|
std::string thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) {
|
||||||
Reg n = n_hi ? (n_lo + 8) : n_lo;
|
const Reg n = n_hi ? (n_lo + 8) : n_lo;
|
||||||
return fmt::format("cmp {}, {}", n, m);
|
return fmt::format("cmp {}, {}", n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) {
|
std::string thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) {
|
||||||
Reg d = d_hi ? (d_lo + 8) : d_lo;
|
const Reg d = d_hi ? (d_lo + 8) : d_lo;
|
||||||
return fmt::format("mov {}, {}", d, m);
|
return fmt::format("mov {}, {}", d, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LDR_literal(Reg t, Imm8 imm8) {
|
std::string thumb16_LDR_literal(Reg t, Imm<8> imm8) {
|
||||||
u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
return fmt::format("ldr {}, [pc, #{}]", t, imm32);
|
return fmt::format("ldr {}, [pc, #{}]", t, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,63 +186,63 @@ public:
|
||||||
return fmt::format("ldrsh {}, [{}, {}]", t, n, m);
|
return fmt::format("ldrsh {}, [{}, {}]", t, n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_STR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
return fmt::format("str {}, [{}, #{}]", t, n, imm32);
|
return fmt::format("str {}, [{}, #{}]", t, n, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
return fmt::format("ldr {}, [{}, #{}]", t, n, imm32);
|
return fmt::format("ldr {}, [{}, #{}]", t, n, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_STRB_imm(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5;
|
const u32 imm32 = imm5.ZeroExtend();
|
||||||
return fmt::format("strb {}, [{}, #{}]", t, n, imm32);
|
return fmt::format("strb {}, [{}, #{}]", t, n, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LDRB_imm(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5;
|
const u32 imm32 = imm5.ZeroExtend();
|
||||||
return fmt::format("ldrb {}, [{}, #{}]", t, n, imm32);
|
return fmt::format("ldrb {}, [{}, #{}]", t, n, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_STRH_imm(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 1;
|
const u32 imm32 = imm5.ZeroExtend() << 1;
|
||||||
return fmt::format("strh {}, [{}, #{}]", t, n, imm32);
|
return fmt::format("strh {}, [{}, #{}]", t, n, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LDRH_imm(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 1;
|
const u32 imm32 = imm5.ZeroExtend() << 1;
|
||||||
return fmt::format("ldrh {}, [{}, #{}]", t, n, imm32);
|
return fmt::format("ldrh {}, [{}, #{}]", t, n, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_STR_imm_t2(Reg t, Imm5 imm5) {
|
std::string thumb16_STR_imm_t2(Reg t, Imm<5> imm5) {
|
||||||
u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
return fmt::format("str {}, [sp, #{}]", t, imm32);
|
return fmt::format("str {}, [sp, #{}]", t, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LDR_imm_t2(Reg t, Imm5 imm5) {
|
std::string thumb16_LDR_imm_t2(Reg t, Imm<5> imm5) {
|
||||||
u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
return fmt::format("ldr {}, [sp, #{}]", t, imm32);
|
return fmt::format("ldr {}, [sp, #{}]", t, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADR(Reg d, Imm8 imm8) {
|
std::string thumb16_ADR(Reg d, Imm<8> imm8) {
|
||||||
u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
return fmt::format("adr {}, +#{}", d, imm32);
|
return fmt::format("adr {}, +#{}", d, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADD_sp_t1(Reg d, Imm8 imm8) {
|
std::string thumb16_ADD_sp_t1(Reg d, Imm<8> imm8) {
|
||||||
u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
return fmt::format("add {}, sp, #{}", d, imm32);
|
return fmt::format("add {}, sp, #{}", d, imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_ADD_sp_t2(Imm7 imm7) {
|
std::string thumb16_ADD_sp_t2(Imm<7> imm7) {
|
||||||
u32 imm32 = imm7 << 2;
|
const u32 imm32 = imm7.ZeroExtend() << 2;
|
||||||
return fmt::format("add sp, sp, #{}", imm32);
|
return fmt::format("add sp, sp, #{}", imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_SUB_sp(Imm7 imm7) {
|
std::string thumb16_SUB_sp(Imm<7> imm7) {
|
||||||
u32 imm32 = imm7 << 2;
|
const u32 imm32 = imm7.ZeroExtend() << 2;
|
||||||
return fmt::format("sub sp, sp, #{}", imm32);
|
return fmt::format("sub sp, sp, #{}", imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +297,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_LDMIA(Reg n, RegList reg_list) {
|
std::string thumb16_LDMIA(Reg n, RegList reg_list) {
|
||||||
bool write_back = !Common::Bit(static_cast<size_t>(n), reg_list);
|
const bool write_back = !Common::Bit(static_cast<size_t>(n), reg_list);
|
||||||
return fmt::format("ldm {}{}, {{{}}}", n, write_back ? "!" : "", RegListToString(reg_list));
|
return fmt::format("ldm {}{}, {{{}}}", n, write_back ? "!" : "", RegListToString(reg_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,18 +313,23 @@ public:
|
||||||
return fmt::format("udf");
|
return fmt::format("udf");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_SVC(Imm8 imm8) {
|
std::string thumb16_SVC(Imm<8> imm8) {
|
||||||
return fmt::format("svc #{}", imm8);
|
return fmt::format("svc #{}", imm8.ZeroExtend());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_B_t1(Cond cond, Imm8 imm8) {
|
std::string thumb16_B_t1(Cond cond, Imm<8> imm8) {
|
||||||
s32 imm32 = Common::SignExtend<9, s32>(imm8 << 1) + 4;
|
const s32 imm32 = static_cast<s32>((imm8.SignExtend<u32>() << 1) + 4);
|
||||||
return fmt::format("b{} {}#{}", CondToString(cond), Common::SignToChar(imm32), abs(imm32));
|
return fmt::format("b{} {}#{}",
|
||||||
|
CondToString(cond),
|
||||||
|
Common::SignToChar(imm32),
|
||||||
|
abs(imm32));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_B_t2(Imm11 imm11) {
|
std::string thumb16_B_t2(Imm<11> imm11) {
|
||||||
s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4;
|
const s32 imm32 = static_cast<s32>((imm11.SignExtend<u32>() << 1) + 4);
|
||||||
return fmt::format("b {}#{}", Common::SignToChar(imm32), abs(imm32));
|
return fmt::format("b {}#{}",
|
||||||
|
Common::SignToChar(imm32),
|
||||||
|
abs(imm32));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -157,22 +157,26 @@ bool ArmTranslatorVisitor::UndefinedInstruction() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::ResultAndCarry<IR::U32> ArmTranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm5 imm5, IR::U1 carry_in) {
|
IR::ResultAndCarry<IR::U32> ArmTranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in) {
|
||||||
|
u8 imm5_value = imm5.ZeroExtend<u8>();
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ShiftType::LSL:
|
case ShiftType::LSL:
|
||||||
return ir.LogicalShiftLeft(value, ir.Imm8(imm5), carry_in);
|
return ir.LogicalShiftLeft(value, ir.Imm8(imm5_value), carry_in);
|
||||||
case ShiftType::LSR:
|
case ShiftType::LSR:
|
||||||
imm5 = imm5 ? imm5 : 32;
|
imm5_value = imm5_value ? imm5_value : 32;
|
||||||
return ir.LogicalShiftRight(value, ir.Imm8(imm5), carry_in);
|
return ir.LogicalShiftRight(value, ir.Imm8(imm5_value), carry_in);
|
||||||
case ShiftType::ASR:
|
case ShiftType::ASR:
|
||||||
imm5 = imm5 ? imm5 : 32;
|
imm5_value = imm5_value ? imm5_value : 32;
|
||||||
return ir.ArithmeticShiftRight(value, ir.Imm8(imm5), carry_in);
|
return ir.ArithmeticShiftRight(value, ir.Imm8(imm5_value), carry_in);
|
||||||
case ShiftType::ROR:
|
case ShiftType::ROR:
|
||||||
if (imm5)
|
if (imm5_value) {
|
||||||
return ir.RotateRight(value, ir.Imm8(imm5), carry_in);
|
return ir.RotateRight(value, ir.Imm8(imm5_value), carry_in);
|
||||||
else
|
} else {
|
||||||
return ir.RotateRightExtended(value, carry_in);
|
return ir.RotateRightExtended(value, carry_in);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,17 @@
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_DMB([[maybe_unused]] Imm4 option) {
|
bool ArmTranslatorVisitor::arm_DMB([[maybe_unused]] Imm<4> option) {
|
||||||
ir.DataMemoryBarrier();
|
ir.DataMemoryBarrier();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_DSB([[maybe_unused]] Imm4 option) {
|
bool ArmTranslatorVisitor::arm_DSB([[maybe_unused]] Imm<4> option) {
|
||||||
ir.DataSynchronizationBarrier();
|
ir.DataSynchronizationBarrier();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ISB([[maybe_unused]] Imm4 option) {
|
bool ArmTranslatorVisitor::arm_ISB([[maybe_unused]] Imm<4> option) {
|
||||||
ir.InstructionSynchronizationBarrier();
|
ir.InstructionSynchronizationBarrier();
|
||||||
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
|
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
|
|
@ -11,19 +11,19 @@
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
// B <label>
|
// B <label>
|
||||||
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) {
|
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm<24> imm24) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8;
|
const u32 imm32 = Common::SignExtend<26, u32>(imm24.ZeroExtend() << 2) + 8;
|
||||||
const auto new_location = ir.current_location.AdvancePC(imm32);
|
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BL <label>
|
// BL <label>
|
||||||
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
|
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm<24> imm24) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -31,18 +31,18 @@ bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
|
||||||
ir.PushRSB(ir.current_location.AdvancePC(4));
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
||||||
|
|
||||||
const u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8;
|
const u32 imm32 = Common::SignExtend<26, u32>(imm24.ZeroExtend() << 2) + 8;
|
||||||
const auto new_location = ir.current_location.AdvancePC(imm32);
|
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BLX <label>
|
// BLX <label>
|
||||||
bool ArmTranslatorVisitor::arm_BLX_imm(bool H, Imm24 imm24) {
|
bool ArmTranslatorVisitor::arm_BLX_imm(bool H, Imm<24> imm24) {
|
||||||
ir.PushRSB(ir.current_location.AdvancePC(4));
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
||||||
|
|
||||||
const u32 imm32 = Common::SignExtend<26, u32>((imm24 << 2)) + (H ? 2 : 0) + 8;
|
const u32 imm32 = Common::SignExtend<26, u32>((imm24.ZeroExtend() << 2)) + (H ? 2 : 0) + 8;
|
||||||
const auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true);
|
const auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true);
|
||||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -25,7 +25,7 @@ bool ArmTranslatorVisitor::arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, Coproc
|
||||||
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>, #+/-<imm32>]{!}
|
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>, #+/-<imm32>]{!}
|
||||||
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], #+/-<imm32>
|
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], #+/-<imm32>
|
||||||
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], <imm8>
|
// LDC{2}{L}<c> <coproc_no>, <CRd>, [<Rn>], <imm8>
|
||||||
bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
|
||||||
if (!p && !u && !d && !w) {
|
if (!p && !u && !d && !w) {
|
||||||
return arm_UDF();
|
return arm_UDF();
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Re
|
||||||
const bool two = cond == Cond::NV;
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
if (two || ConditionPassed(cond)) {
|
if (two || ConditionPassed(cond)) {
|
||||||
const u32 imm32 = static_cast<u8>(imm8) << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const bool index = p;
|
const bool index = p;
|
||||||
const bool add = u;
|
const bool add = u;
|
||||||
const bool wback = w;
|
const bool wback = w;
|
||||||
|
@ -45,7 +45,7 @@ bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Re
|
||||||
const IR::U32 reg_n = ir.GetRegister(n);
|
const IR::U32 reg_n = ir.GetRegister(n);
|
||||||
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
|
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
|
||||||
const IR::U32 address = index ? offset_address : reg_n;
|
const IR::U32 address = index ? offset_address : reg_n;
|
||||||
ir.CoprocLoadWords(coproc_no, two, d, CRd, address, has_option, imm8);
|
ir.CoprocLoadWords(coproc_no, two, d, CRd, address, has_option, imm8.ZeroExtend<u8>());
|
||||||
if (wback) {
|
if (wback) {
|
||||||
ir.SetRegister(n, offset_address);
|
ir.SetRegister(n, offset_address);
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ bool ArmTranslatorVisitor::arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no,
|
||||||
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>, #+/-<imm32>]{!}
|
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>, #+/-<imm32>]{!}
|
||||||
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], #+/-<imm32>
|
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], #+/-<imm32>
|
||||||
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], <imm8>
|
// STC{2}{L}<c> <coproc>, <CRd>, [<Rn>], <imm8>
|
||||||
bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
|
||||||
if ((coproc_no & 0b1110) == 0b1010) {
|
if ((coproc_no & 0b1110) == 0b1010) {
|
||||||
return arm_UDF();
|
return arm_UDF();
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Re
|
||||||
const bool two = cond == Cond::NV;
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
if (two || ConditionPassed(cond)) {
|
if (two || ConditionPassed(cond)) {
|
||||||
const u32 imm32 = static_cast<u8>(imm8) << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const bool index = p;
|
const bool index = p;
|
||||||
const bool add = u;
|
const bool add = u;
|
||||||
const bool wback = w;
|
const bool wback = w;
|
||||||
|
@ -156,7 +156,7 @@ bool ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Re
|
||||||
const IR::U32 reg_n = ir.GetRegister(n);
|
const IR::U32 reg_n = ir.GetRegister(n);
|
||||||
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
|
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
|
||||||
const IR::U32 address = index ? offset_address : reg_n;
|
const IR::U32 address = index ? offset_address : reg_n;
|
||||||
ir.CoprocStoreWords(coproc_no, two, d, CRd, address, has_option, imm8);
|
ir.CoprocStoreWords(coproc_no, two, d, CRd, address, has_option, imm8.ZeroExtend<u8>());
|
||||||
if (wback) {
|
if (wback) {
|
||||||
ir.SetRegister(n, offset_address);
|
ir.SetRegister(n, offset_address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
// ADC{S}<c> <Rd>, <Rn>, #<imm>
|
// ADC{S}<c> <Rd>, <Rn>, #<imm>
|
||||||
bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ bool ArmTranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD{S}<c> <Rd>, <Rn>, #<const>
|
// ADD{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ bool ArmTranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// AND{S}<c> <Rd>, <Rn>, #<const>
|
// AND{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ bool ArmTranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// BIC{S}<c> <Rd>, <Rn>, #<const>
|
// BIC{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +292,7 @@ bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ bool ArmTranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMN<c> <Rn>, #<const>
|
// CMN<c> <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -363,7 +363,7 @@ bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMN<c> <Rn>, <Rm>{, <shift>}
|
// CMN<c> <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,7 @@ bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMP<c> <Rn>, #<imm>
|
// CMP<c> <Rn>, #<imm>
|
||||||
bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMP<c> <Rn>, <Rm>{, <shift>}
|
// CMP<c> <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -455,7 +455,7 @@ bool ArmTranslatorVisitor::arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOR{S}<c> <Rd>, <Rn>, #<const>
|
// EOR{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -539,7 +539,7 @@ bool ArmTranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// MOV{S}<c> <Rd>, #<const>
|
// MOV{S}<c> <Rd>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -568,7 +568,7 @@ bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm
|
||||||
}
|
}
|
||||||
|
|
||||||
// MOV{S}<c> <Rd>, <Rm>
|
// MOV{S}<c> <Rd>, <Rm>
|
||||||
bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -621,7 +621,7 @@ bool ArmTranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
// MVN{S}<c> <Rd>, #<const>
|
// MVN{S}<c> <Rd>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -650,7 +650,7 @@ bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm
|
||||||
}
|
}
|
||||||
|
|
||||||
// MVN{S}<c> <Rd>, <Rm>{, <shift>}
|
// MVN{S}<c> <Rd>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -705,7 +705,7 @@ bool ArmTranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORR{S}<c> <Rd>, <Rn>, #<const>
|
// ORR{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +734,7 @@ bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -789,7 +789,7 @@ bool ArmTranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSB{S}<c> <Rd>, <Rn>, #<const>
|
// RSB{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -819,7 +819,7 @@ bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -875,7 +875,7 @@ bool ArmTranslatorVisitor::arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSC{S}<c> <Rd>, <Rn>, #<const>
|
// RSC{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -904,7 +904,7 @@ bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -960,7 +960,7 @@ bool ArmTranslatorVisitor::arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBC{S}<c> <Rd>, <Rn>, #<const>
|
// SBC{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -990,7 +990,7 @@ bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1046,7 @@ bool ArmTranslatorVisitor::arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUB{S}<c> <Rd>, <Rn>, #<const>
|
// SUB{S}<c> <Rd>, <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1076,7 +1076,7 @@ bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
// SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1131,7 @@ bool ArmTranslatorVisitor::arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, S
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEQ<c> <Rn>, #<const>
|
// TEQ<c> <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1146,7 +1146,7 @@ bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEQ<c> <Rn>, <Rm>{, <shift>}
|
// TEQ<c> <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1183,7 +1183,7 @@ bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TST<c> <Rn>, #<const>
|
// TST<c> <Rn>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1198,7 @@ bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TST<c> <Rn>, <Rm>{, <shift>}
|
// TST<c> <Rn>, <Rm>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
// BKPT #<imm16>
|
// BKPT #<imm16>
|
||||||
bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm12 /*imm12*/, Imm4 /*imm4*/) {
|
bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) {
|
||||||
if (cond != Cond::AL && !options.define_unpredictable_behaviour) {
|
if (cond != Cond::AL && !options.define_unpredictable_behaviour) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,12 @@ bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm12 /*imm12*/, Imm4 /*imm4*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SVC<c> #<imm24>
|
// SVC<c> #<imm24>
|
||||||
bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) {
|
bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm<24> imm24) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm24;
|
const u32 imm32 = imm24.ZeroExtend();
|
||||||
ir.PushRSB(ir.current_location.AdvancePC(4));
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
|
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
|
||||||
ir.CallSupervisor(ir.Imm32(imm32));
|
ir.CallSupervisor(ir.Imm32(imm32));
|
||||||
|
|
|
@ -56,14 +56,14 @@ static IR::U32 GetAddress(A32::IREmitter& ir, bool P, bool U, bool W, Reg n, IR:
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDR <Rt>, [PC, #+/-<imm>]
|
// LDR <Rt>, [PC, #+/-<imm>]
|
||||||
bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool add = U;
|
const bool add = U;
|
||||||
const u32 base = ir.AlignPC(4);
|
const u32 base = ir.AlignPC(4);
|
||||||
const u32 address = add ? (base + imm12) : (base - imm12);
|
const u32 address = add ? (base + imm12.ZeroExtend()) : (base - imm12.ZeroExtend());
|
||||||
const auto data = ir.ReadMemory32(ir.Imm32(address));
|
const auto data = ir.ReadMemory32(ir.Imm32(address));
|
||||||
|
|
||||||
if (t == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
|
@ -78,7 +78,7 @@ bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
||||||
|
|
||||||
// LDR <Rt>, [<Rn>, #+/-<imm>]{!}
|
// LDR <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// LDR <Rt>, [<Rn>], #+/-<imm>
|
// LDR <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
if (n == Reg::PC) {
|
if (n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm12;
|
const u32 imm32 = imm12.ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
const auto data = ir.ReadMemory32(address);
|
const auto data = ir.ReadMemory32(address);
|
||||||
|
@ -115,7 +115,7 @@ bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
|
|
||||||
// LDR <Rt>, [<Rn>, #+/-<Rm>]{!}
|
// LDR <Rt>, [<Rn>, #+/-<Rm>]{!}
|
||||||
// LDR <Rt>, [<Rn>], #+/-<Rm>
|
// LDR <Rt>, [<Rn>], #+/-<Rm>
|
||||||
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
if (m == Reg::PC) {
|
if (m == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -144,7 +144,7 @@ bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDRB <Rt>, [PC, #+/-<imm>]
|
// LDRB <Rt>, [PC, #+/-<imm>]
|
||||||
bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12) {
|
||||||
if (t == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm12;
|
const u32 imm32 = imm12.ZeroExtend();
|
||||||
const bool add = U;
|
const bool add = U;
|
||||||
const u32 base = ir.AlignPC(4);
|
const u32 base = ir.AlignPC(4);
|
||||||
const u32 address = add ? (base + imm32) : (base - imm32);
|
const u32 address = add ? (base + imm32) : (base - imm32);
|
||||||
|
@ -165,7 +165,7 @@ bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
||||||
|
|
||||||
// LDRB <Rt>, [<Rn>, #+/-<imm>]{!}
|
// LDRB <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// LDRB <Rt>, [<Rn>], #+/-<imm>
|
// LDRB <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
if (n == Reg::PC) {
|
if (n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm12;
|
const u32 imm32 = imm12.ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
|
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
|
||||||
|
@ -194,7 +194,7 @@ bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
|
|
||||||
// LDRB <Rt>, [<Rn>, #+/-<Rm>]{!}
|
// LDRB <Rt>, [<Rn>, #+/-<Rm>]{!}
|
||||||
// LDRB <Rt>, [<Rn>], #+/-<Rm>
|
// LDRB <Rt>, [<Rn>], #+/-<Rm>
|
||||||
bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
if (t == Reg::PC || m == Reg::PC) {
|
if (t == Reg::PC || m == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -217,7 +217,7 @@ bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDRD <Rt>, <Rt2>, [PC, #+/-<imm>]
|
// LDRD <Rt>, <Rt2>, [PC, #+/-<imm>]
|
||||||
bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (RegNumber(t) % 2 == 1) {
|
if (RegNumber(t) % 2 == 1) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Im
|
||||||
}
|
}
|
||||||
|
|
||||||
const Reg t2 = t+1;
|
const Reg t2 = t+1;
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const bool add = U;
|
const bool add = U;
|
||||||
|
|
||||||
const u32 base = ir.AlignPC(4);
|
const u32 base = ir.AlignPC(4);
|
||||||
|
@ -246,7 +246,7 @@ bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Im
|
||||||
|
|
||||||
// LDRD <Rt>, [<Rn>, #+/-<imm>]{!}
|
// LDRD <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// LDRD <Rt>, [<Rn>], #+/-<imm>
|
// LDRD <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (n == Reg::PC) {
|
if (n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
}
|
}
|
||||||
|
|
||||||
const Reg t2 = t+1;
|
const Reg t2 = t+1;
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
|
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address_a = GetAddress(ir, P, U, W, n, offset);
|
const auto address_a = GetAddress(ir, P, U, W, n, offset);
|
||||||
|
@ -321,7 +321,7 @@ bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDRH <Rt>, [PC, #-/+<imm>]
|
// LDRH <Rt>, [PC, #-/+<imm>]
|
||||||
bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
if (P == W) {
|
if (P == W) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -335,7 +335,7 @@ bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const bool add = U;
|
const bool add = U;
|
||||||
const u32 base = ir.AlignPC(4);
|
const u32 base = ir.AlignPC(4);
|
||||||
const u32 address = add ? (base + imm32) : (base - imm32);
|
const u32 address = add ? (base + imm32) : (base - imm32);
|
||||||
|
@ -347,7 +347,7 @@ bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t
|
||||||
|
|
||||||
// LDRH <Rt>, [<Rn>, #+/-<imm>]{!}
|
// LDRH <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// LDRH <Rt>, [<Rn>], #+/-<imm>
|
// LDRH <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (n == Reg::PC) {
|
if (n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
|
||||||
|
@ -399,7 +399,7 @@ bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDRSB <Rt>, [PC, #+/-<imm>]
|
// LDRSB <Rt>, [PC, #+/-<imm>]
|
||||||
bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (t == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const bool add = U;
|
const bool add = U;
|
||||||
|
|
||||||
const u32 base = ir.AlignPC(4);
|
const u32 base = ir.AlignPC(4);
|
||||||
|
@ -421,7 +421,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
|
||||||
|
|
||||||
// LDRSB <Rt>, [<Rn>, #+/-<imm>]{!}
|
// LDRSB <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// LDRSB <Rt>, [<Rn>], #+/-<imm>
|
// LDRSB <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (n == Reg::PC) {
|
if (n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address));
|
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address));
|
||||||
|
@ -473,7 +473,7 @@ bool ArmTranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDRSH <Rt>, [PC, #-/+<imm>]
|
// LDRSH <Rt>, [PC, #-/+<imm>]
|
||||||
bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (t == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -482,7 +482,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const bool add = U;
|
const bool add = U;
|
||||||
const u32 base = ir.AlignPC(4);
|
const u32 base = ir.AlignPC(4);
|
||||||
const u32 address = add ? (base + imm32) : (base - imm32);
|
const u32 address = add ? (base + imm32) : (base - imm32);
|
||||||
|
@ -494,7 +494,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, I
|
||||||
|
|
||||||
// LDRSH <Rt>, [<Rn>, #+/-<imm>]{!}
|
// LDRSH <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// LDRSH <Rt>, [<Rn>], #+/-<imm>
|
// LDRSH <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (n == Reg::PC) {
|
if (n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -512,7 +512,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = (imm8a << 4) | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address));
|
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address));
|
||||||
|
@ -547,7 +547,7 @@ bool ArmTranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg
|
||||||
|
|
||||||
// STR <Rt>, [<Rn>, #+/-<imm>]{!}
|
// STR <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// STR <Rt>, [<Rn>], #+/-<imm>
|
// STR <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
if ((!P || W) && (n == Reg::PC || n == t)) {
|
if ((!P || W) && (n == Reg::PC || n == t)) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -556,7 +556,7 @@ bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto offset = ir.Imm32(imm12);
|
const auto offset = ir.Imm32(imm12.ZeroExtend());
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
ir.WriteMemory32(address, ir.GetRegister(t));
|
ir.WriteMemory32(address, ir.GetRegister(t));
|
||||||
return true;
|
return true;
|
||||||
|
@ -564,7 +564,7 @@ bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
|
|
||||||
// STR <Rt>, [<Rn>, #+/-<Rm>]{!}
|
// STR <Rt>, [<Rn>, #+/-<Rm>]{!}
|
||||||
// STR <Rt>, [<Rn>], #+/-<Rm>
|
// STR <Rt>, [<Rn>], #+/-<Rm>
|
||||||
bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (m == Reg::PC) {
|
if (m == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -585,7 +585,7 @@ bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
|
|
||||||
// STRB <Rt>, [<Rn>, #+/-<imm>]{!}
|
// STRB <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// STRB <Rt>, [<Rn>], #+/-<imm>
|
// STRB <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12) {
|
||||||
if (t == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,7 @@ bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto offset = ir.Imm32(imm12);
|
const auto offset = ir.Imm32(imm12.ZeroExtend());
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)));
|
ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)));
|
||||||
return true;
|
return true;
|
||||||
|
@ -606,7 +606,7 @@ bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
|
|
||||||
// STRB <Rt>, [<Rn>, #+/-<Rm>]{!}
|
// STRB <Rt>, [<Rn>, #+/-<Rm>]{!}
|
||||||
// STRB <Rt>, [<Rn>], #+/-<Rm>
|
// STRB <Rt>, [<Rn>], #+/-<Rm>
|
||||||
bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m) {
|
||||||
if (t == Reg::PC || m == Reg::PC) {
|
if (t == Reg::PC || m == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -627,7 +627,7 @@ bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
|
|
||||||
// STRD <Rt>, [<Rn>, #+/-<imm>]{!}
|
// STRD <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// STRD <Rt>, [<Rn>], #+/-<imm>
|
// STRD <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (size_t(t) % 2 != 0) {
|
if (size_t(t) % 2 != 0) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -649,7 +649,7 @@ bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8a << 4 | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address_a = GetAddress(ir, P, U, W, n, offset);
|
const auto address_a = GetAddress(ir, P, U, W, n, offset);
|
||||||
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
||||||
|
@ -698,7 +698,7 @@ bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
|
|
||||||
// STRH <Rt>, [<Rn>, #+/-<imm>]{!}
|
// STRH <Rt>, [<Rn>, #+/-<imm>]{!}
|
||||||
// STRH <Rt>, [<Rn>], #+/-<imm>
|
// STRH <Rt>, [<Rn>], #+/-<imm>
|
||||||
bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b) {
|
||||||
if (t == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -711,7 +711,7 @@ bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8a << 4 | imm8b;
|
const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend();
|
||||||
const auto offset = ir.Imm32(imm32);
|
const auto offset = ir.Imm32(imm32);
|
||||||
const auto address = GetAddress(ir, P, U, W, n, offset);
|
const auto address = GetAddress(ir, P, U, W, n, offset);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
// BFC<c> <Rd>, #<lsb>, #<width>
|
// BFC<c> <Rd>, #<lsb>, #<width>
|
||||||
bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
|
bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb) {
|
||||||
if (d == Reg::PC) {
|
if (d == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,9 @@ bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 mask = ~(Common::Ones<u32>(msb - lsb + 1) << lsb);
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 msb_value = msb.ZeroExtend();
|
||||||
|
const u32 mask = ~(Common::Ones<u32>(msb_value - lsb_value + 1) << lsb_value);
|
||||||
const IR::U32 operand = ir.GetRegister(d);
|
const IR::U32 operand = ir.GetRegister(d);
|
||||||
const IR::U32 result = ir.And(operand, ir.Imm32(mask));
|
const IR::U32 result = ir.And(operand, ir.Imm32(mask));
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ bool ArmTranslatorVisitor::arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
|
// BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||||
bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n) {
|
bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n) {
|
||||||
if (d == Reg::PC) {
|
if (d == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -43,10 +45,12 @@ bool ArmTranslatorVisitor::arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 inclusion_mask = Common::Ones<u32>(msb - lsb + 1) << lsb;
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 msb_value = msb.ZeroExtend();
|
||||||
|
const u32 inclusion_mask = Common::Ones<u32>(msb_value - lsb_value + 1) << lsb_value;
|
||||||
const u32 exclusion_mask = ~inclusion_mask;
|
const u32 exclusion_mask = ~inclusion_mask;
|
||||||
const IR::U32 operand1 = ir.And(ir.GetRegister(d), ir.Imm32(exclusion_mask));
|
const IR::U32 operand1 = ir.And(ir.GetRegister(d), ir.Imm32(exclusion_mask));
|
||||||
const IR::U32 operand2 = ir.And(ir.LogicalShiftLeft(ir.GetRegister(n), ir.Imm8(lsb)), ir.Imm32(inclusion_mask));
|
const IR::U32 operand2 = ir.And(ir.LogicalShiftLeft(ir.GetRegister(n), ir.Imm8(u8(lsb_value))), ir.Imm32(inclusion_mask));
|
||||||
const IR::U32 result = ir.Or(operand1, operand2);
|
const IR::U32 result = ir.Or(operand1, operand2);
|
||||||
|
|
||||||
ir.SetRegister(d, result);
|
ir.SetRegister(d, result);
|
||||||
|
@ -68,7 +72,7 @@ bool ArmTranslatorVisitor::arm_CLZ(Cond cond, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MOVT<c> <Rd>, #<imm16>
|
// MOVT<c> <Rd>, #<imm16>
|
||||||
bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12) {
|
||||||
if (d == Reg::PC) {
|
if (d == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -77,7 +81,7 @@ bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IR::U32 imm16 = ir.Imm32(((u32(imm4) << 12 | u32(imm12)) << 16));
|
const IR::U32 imm16 = ir.Imm32(concatenate(imm4, imm12).ZeroExtend() << 16);
|
||||||
const IR::U32 operand = ir.GetRegister(d);
|
const IR::U32 operand = ir.GetRegister(d);
|
||||||
const IR::U32 result = ir.Or(ir.And(operand, ir.Imm32(0x0000FFFFU)), imm16);
|
const IR::U32 result = ir.Or(ir.And(operand, ir.Imm32(0x0000FFFFU)), imm16);
|
||||||
|
|
||||||
|
@ -86,12 +90,14 @@ bool ArmTranslatorVisitor::arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
|
// SBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||||
bool ArmTranslatorVisitor::arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) {
|
bool ArmTranslatorVisitor::arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
|
||||||
if (d == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 msb = u32{lsb} + widthm1;
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 widthm1_value = widthm1.ZeroExtend();
|
||||||
|
const u32 msb = lsb_value + widthm1_value;
|
||||||
if (msb >= Common::BitSize<u32>()) {
|
if (msb >= Common::BitSize<u32>()) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -101,8 +107,8 @@ bool ArmTranslatorVisitor::arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Re
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t max_width = Common::BitSize<u32>();
|
constexpr size_t max_width = Common::BitSize<u32>();
|
||||||
const u8 width = widthm1 + 1;
|
const u32 width = widthm1_value + 1;
|
||||||
const u8 left_shift_amount = static_cast<u8>(max_width - width - lsb);
|
const u8 left_shift_amount = static_cast<u8>(max_width - width - lsb_value);
|
||||||
const u8 right_shift_amount = static_cast<u8>(max_width - width);
|
const u8 right_shift_amount = static_cast<u8>(max_width - width);
|
||||||
const IR::U32 operand = ir.GetRegister(n);
|
const IR::U32 operand = ir.GetRegister(n);
|
||||||
const IR::U32 tmp = ir.LogicalShiftLeft(operand, ir.Imm8(left_shift_amount));
|
const IR::U32 tmp = ir.LogicalShiftLeft(operand, ir.Imm8(left_shift_amount));
|
||||||
|
@ -131,12 +137,14 @@ bool ArmTranslatorVisitor::arm_SEL(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
|
// UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||||
bool ArmTranslatorVisitor::arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n) {
|
bool ArmTranslatorVisitor::arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n) {
|
||||||
if (d == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 msb = u32{lsb} + widthm1;
|
const u32 lsb_value = lsb.ZeroExtend();
|
||||||
|
const u32 widthm1_value = widthm1.ZeroExtend();
|
||||||
|
const u32 msb = lsb_value + widthm1_value;
|
||||||
if (msb >= Common::BitSize<u32>()) {
|
if (msb >= Common::BitSize<u32>()) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -146,8 +154,8 @@ bool ArmTranslatorVisitor::arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Re
|
||||||
}
|
}
|
||||||
|
|
||||||
const IR::U32 operand = ir.GetRegister(n);
|
const IR::U32 operand = ir.GetRegister(n);
|
||||||
const IR::U32 mask = ir.Imm32(Common::Ones<u32>(widthm1 + 1));
|
const IR::U32 mask = ir.Imm32(Common::Ones<u32>(widthm1_value + 1));
|
||||||
const IR::U32 result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(lsb)), mask);
|
const IR::U32 result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(u8(lsb_value))), mask);
|
||||||
|
|
||||||
ir.SetRegister(d, result);
|
ir.SetRegister(d, result);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
// PKHBT<c> <Rd>, <Rn>, <Rm>{, LSL #<imm>}
|
// PKHBT<c> <Rd>, <Rn>, <Rm>{, LSL #<imm>}
|
||||||
bool ArmTranslatorVisitor::arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) {
|
bool ArmTranslatorVisitor::arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
|
||||||
if (n == Reg::PC || d == Reg::PC || m == Reg::PC) {
|
if (n == Reg::PC || d == Reg::PC || m == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ bool ArmTranslatorVisitor::arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PKHTB<c> <Rd>, <Rn>, <Rm>{, ASR #<imm>}
|
// PKHTB<c> <Rd>, <Rn>, <Rm>{, ASR #<imm>}
|
||||||
bool ArmTranslatorVisitor::arm_PKHTB(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m) {
|
bool ArmTranslatorVisitor::arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m) {
|
||||||
if (n == Reg::PC || d == Reg::PC || m == Reg::PC) {
|
if (n == Reg::PC || d == Reg::PC || m == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
|
||||||
// Saturation instructions
|
// Saturation instructions
|
||||||
|
|
||||||
// SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
|
// SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) {
|
bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
|
||||||
if (d == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto saturate_to = static_cast<size_t>(sat_imm) + 1;
|
const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend()) + 1;
|
||||||
const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR;
|
const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR;
|
||||||
const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
|
const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
|
||||||
const auto result = ir.SignedSaturation(operand.result, saturate_to);
|
const auto result = ir.SignedSaturation(operand.result, saturate_to);
|
||||||
|
@ -39,7 +39,7 @@ bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSAT16<c> <Rd>, #<imm>, <Rn>
|
// SSAT16<c> <Rd>, #<imm>, <Rn>
|
||||||
bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
|
||||||
if (d == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto saturate_to = static_cast<size_t>(sat_imm) + 1;
|
const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend()) + 1;
|
||||||
const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n)));
|
const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n)));
|
||||||
const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
|
const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
|
||||||
const auto lo_result = ir.SignedSaturation(lo_operand, saturate_to);
|
const auto lo_result = ir.SignedSaturation(lo_operand, saturate_to);
|
||||||
|
@ -61,7 +61,7 @@ bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// USAT<c> <Rd>, #<imm5>, <Rn>{, <shift>}
|
// USAT<c> <Rd>, #<imm5>, <Rn>{, <shift>}
|
||||||
bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) {
|
bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n) {
|
||||||
if (d == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto saturate_to = static_cast<size_t>(sat_imm);
|
const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend());
|
||||||
const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR;
|
const auto shift = !sh ? ShiftType::LSL : ShiftType::ASR;
|
||||||
const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
|
const auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag());
|
||||||
const auto result = ir.UnsignedSaturation(operand.result, saturate_to);
|
const auto result = ir.UnsignedSaturation(operand.result, saturate_to);
|
||||||
|
@ -81,7 +81,7 @@ bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, b
|
||||||
}
|
}
|
||||||
|
|
||||||
// USAT16<c> <Rd>, #<imm4>, <Rn>
|
// USAT16<c> <Rd>, #<imm4>, <Rn>
|
||||||
bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n) {
|
||||||
if (d == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnsignedSaturation takes a *signed* value as input, hence sign extension is required.
|
// UnsignedSaturation takes a *signed* value as input, hence sign extension is required.
|
||||||
const auto saturate_to = static_cast<size_t>(sat_imm);
|
const auto saturate_to = static_cast<size_t>(sat_imm.ZeroExtend());
|
||||||
const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n)));
|
const auto lo_operand = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(ir.GetRegister(n)));
|
||||||
const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
|
const auto hi_operand = ir.SignExtendHalfToWord(MostSignificantHalf(ir, ir.GetRegister(n)));
|
||||||
const auto lo_result = ir.UnsignedSaturation(lo_operand, saturate_to);
|
const auto lo_result = ir.UnsignedSaturation(lo_operand, saturate_to);
|
||||||
|
|
|
@ -31,7 +31,7 @@ bool ArmTranslatorVisitor::arm_MRS(Cond cond, Reg d) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSR<c> <spec_reg>, #<const>
|
// MSR<c> <spec_reg>, #<const>
|
||||||
bool ArmTranslatorVisitor::arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8) {
|
||||||
ASSERT_MSG(mask != 0, "Decode error");
|
ASSERT_MSG(mask != 0, "Decode error");
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
|
#include "frontend/imm.h"
|
||||||
#include "frontend/A32/ir_emitter.h"
|
#include "frontend/A32/ir_emitter.h"
|
||||||
#include "frontend/A32/location_descriptor.h"
|
#include "frontend/A32/location_descriptor.h"
|
||||||
#include "frontend/A32/translate/translate.h"
|
#include "frontend/A32/translate/translate.h"
|
||||||
|
@ -40,8 +41,8 @@ struct ArmTranslatorVisitor final {
|
||||||
bool UnpredictableInstruction();
|
bool UnpredictableInstruction();
|
||||||
bool UndefinedInstruction();
|
bool UndefinedInstruction();
|
||||||
|
|
||||||
static u32 ArmExpandImm(int rotate, Imm8 imm8) {
|
static u32 ArmExpandImm(int rotate, Imm<8> imm8) {
|
||||||
return Common::RotateRight<u32>(imm8, rotate * 2);
|
return Common::RotateRight<u32>(imm8.ZeroExtend(), rotate * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImmAndCarry {
|
struct ImmAndCarry {
|
||||||
|
@ -49,96 +50,96 @@ struct ArmTranslatorVisitor final {
|
||||||
IR::U1 carry;
|
IR::U1 carry;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImmAndCarry ArmExpandImm_C(int rotate, u32 imm8, IR::U1 carry_in) {
|
ImmAndCarry ArmExpandImm_C(int rotate, Imm<8> imm8, IR::U1 carry_in) {
|
||||||
u32 imm32 = imm8;
|
u32 imm32 = imm8.ZeroExtend();
|
||||||
auto carry_out = carry_in;
|
auto carry_out = carry_in;
|
||||||
if (rotate) {
|
if (rotate) {
|
||||||
imm32 = ArmExpandImm(rotate, static_cast<Imm8>(imm8));
|
imm32 = ArmExpandImm(rotate, imm8);
|
||||||
carry_out = ir.Imm1(Common::Bit<31>(imm32));
|
carry_out = ir.Imm1(Common::Bit<31>(imm32));
|
||||||
}
|
}
|
||||||
return {imm32, carry_out};
|
return {imm32, carry_out};
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm5 imm5, IR::U1 carry_in);
|
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in);
|
||||||
IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in);
|
IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in);
|
||||||
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
|
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
|
||||||
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);
|
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);
|
||||||
|
|
||||||
// Barrier instructions
|
// Barrier instructions
|
||||||
bool arm_DMB(Imm4 option);
|
bool arm_DMB(Imm<4> option);
|
||||||
bool arm_DSB(Imm4 option);
|
bool arm_DSB(Imm<4> option);
|
||||||
bool arm_ISB(Imm4 option);
|
bool arm_ISB(Imm<4> option);
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
bool arm_B(Cond cond, Imm24 imm24);
|
bool arm_B(Cond cond, Imm<24> imm24);
|
||||||
bool arm_BL(Cond cond, Imm24 imm24);
|
bool arm_BL(Cond cond, Imm<24> imm24);
|
||||||
bool arm_BLX_imm(bool H, Imm24 imm24);
|
bool arm_BLX_imm(bool H, Imm<24> imm24);
|
||||||
bool arm_BLX_reg(Cond cond, Reg m);
|
bool arm_BLX_reg(Cond cond, Reg m);
|
||||||
bool arm_BX(Cond cond, Reg m);
|
bool arm_BX(Cond cond, Reg m);
|
||||||
bool arm_BXJ(Cond cond, Reg m);
|
bool arm_BXJ(Cond cond, Reg m);
|
||||||
|
|
||||||
// Coprocessor instructions
|
// Coprocessor instructions
|
||||||
bool arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
bool arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
bool arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8);
|
bool arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
|
||||||
bool arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
bool arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
bool arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
bool arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
bool arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
bool arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
bool arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
bool arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
bool arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8);
|
bool arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
|
||||||
|
|
||||||
// Data processing instructions
|
// Data processing instructions
|
||||||
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
|
bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
bool arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
|
bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
bool arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8);
|
bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8);
|
bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
|
bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
bool arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8);
|
bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
bool arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
|
|
||||||
// Exception generating instructions
|
// Exception generating instructions
|
||||||
bool arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4);
|
bool arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4);
|
||||||
bool arm_SVC(Cond cond, Imm24 imm24);
|
bool arm_SVC(Cond cond, Imm<24> imm24);
|
||||||
bool arm_UDF();
|
bool arm_UDF();
|
||||||
|
|
||||||
// Extension instructions
|
// Extension instructions
|
||||||
|
@ -171,31 +172,31 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_STRBT();
|
bool arm_STRBT();
|
||||||
bool arm_STRHT();
|
bool arm_STRHT();
|
||||||
bool arm_STRT();
|
bool arm_STRT();
|
||||||
bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12);
|
bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12);
|
||||||
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm<12> imm12);
|
||||||
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12);
|
bool arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12);
|
||||||
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12);
|
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
|
||||||
bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
bool arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
bool arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
bool arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
bool arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
bool arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12);
|
bool arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
|
||||||
bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12);
|
bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
|
||||||
bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
|
|
||||||
// Load/Store multiple instructions
|
// Load/Store multiple instructions
|
||||||
|
@ -212,23 +213,23 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_STM_usr();
|
bool arm_STM_usr();
|
||||||
|
|
||||||
// Miscellaneous instructions
|
// Miscellaneous instructions
|
||||||
bool arm_BFC(Cond cond, Imm5 msb, Reg d, Imm5 lsb);
|
bool arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb);
|
||||||
bool arm_BFI(Cond cond, Imm5 msb, Reg d, Imm5 lsb, Reg n);
|
bool arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n);
|
||||||
bool arm_CLZ(Cond cond, Reg d, Reg m);
|
bool arm_CLZ(Cond cond, Reg d, Reg m);
|
||||||
bool arm_MOVT(Cond cond, Imm4 imm4, Reg d, Imm12 imm12);
|
bool arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
|
||||||
bool arm_NOP() { return true; }
|
bool arm_NOP() { return true; }
|
||||||
bool arm_RBIT(Cond cond, Reg d, Reg m);
|
bool arm_RBIT(Cond cond, Reg d, Reg m);
|
||||||
bool arm_SBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n);
|
bool arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
|
||||||
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
|
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
|
||||||
bool arm_UBFX(Cond cond, Imm5 widthm1, Reg d, Imm5 lsb, Reg n);
|
bool arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
|
||||||
|
|
||||||
// Unsigned sum of absolute difference functions
|
// Unsigned sum of absolute difference functions
|
||||||
bool arm_USAD8(Cond cond, Reg d, Reg m, Reg n);
|
bool arm_USAD8(Cond cond, Reg d, Reg m, Reg n);
|
||||||
bool arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n);
|
bool arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n);
|
||||||
|
|
||||||
// Packing instructions
|
// Packing instructions
|
||||||
bool arm_PKHBT(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m);
|
bool arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m);
|
||||||
bool arm_PKHTB(Cond cond, Reg n, Reg d, Imm5 imm5, Reg m);
|
bool arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m);
|
||||||
|
|
||||||
// Reversal instructions
|
// Reversal instructions
|
||||||
bool arm_REV(Cond cond, Reg d, Reg m);
|
bool arm_REV(Cond cond, Reg d, Reg m);
|
||||||
|
@ -236,10 +237,10 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_REVSH(Cond cond, Reg d, Reg m);
|
bool arm_REVSH(Cond cond, Reg d, Reg m);
|
||||||
|
|
||||||
// Saturation instructions
|
// Saturation instructions
|
||||||
bool arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n);
|
bool arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n);
|
||||||
bool arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n);
|
bool arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n);
|
||||||
bool arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n);
|
bool arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n);
|
||||||
bool arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n);
|
bool arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n);
|
||||||
|
|
||||||
// Divide instructions
|
// Divide instructions
|
||||||
bool arm_SDIV(Cond cond, Reg d, Reg m, Reg n);
|
bool arm_SDIV(Cond cond, Reg d, Reg m, Reg n);
|
||||||
|
@ -343,7 +344,7 @@ struct ArmTranslatorVisitor final {
|
||||||
// Status register access instructions
|
// Status register access instructions
|
||||||
bool arm_CPS();
|
bool arm_CPS();
|
||||||
bool arm_MRS(Cond cond, Reg d);
|
bool arm_MRS(Cond cond, Reg d);
|
||||||
bool arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8);
|
bool arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8);
|
||||||
bool arm_MSR_reg(Cond cond, int mask, Reg n);
|
bool arm_MSR_reg(Cond cond, int mask, Reg n);
|
||||||
bool arm_RFE();
|
bool arm_RFE();
|
||||||
bool arm_SETEND(bool E);
|
bool arm_SETEND(bool E);
|
||||||
|
@ -387,14 +388,14 @@ struct ArmTranslatorVisitor final {
|
||||||
bool vfp2_VMRS(Cond cond, Reg t);
|
bool vfp2_VMRS(Cond cond, Reg t);
|
||||||
|
|
||||||
// Floating-point load-store instructions
|
// Floating-point load-store instructions
|
||||||
bool vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8);
|
bool vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
bool vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8);
|
bool vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
bool vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8);
|
bool vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
bool vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8);
|
bool vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
bool vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8);
|
bool vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
bool vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8);
|
bool vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
bool vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8);
|
bool vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
bool vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8);
|
bool vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -628,9 +628,9 @@ bool ArmTranslatorVisitor::vfp2_VMRS(Cond cond, Reg t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VPOP.{F32,F64} <list>
|
// VPOP.{F32,F64} <list>
|
||||||
bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
const ExtReg d = ToExtReg(sz, Vd, D);
|
const ExtReg d = ToExtReg(sz, Vd, D);
|
||||||
const size_t regs = sz ? imm8 >> 1 : imm8;
|
const size_t regs = sz ? imm8.ZeroExtend() >> 1 : imm8.ZeroExtend();
|
||||||
|
|
||||||
if (regs == 0 || RegNumber(d)+regs > 32) {
|
if (regs == 0 || RegNumber(d)+regs > 32) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -668,9 +668,9 @@ bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8
|
||||||
}
|
}
|
||||||
|
|
||||||
// VPUSH.{F32,F64} <list>
|
// VPUSH.{F32,F64} <list>
|
||||||
bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
const ExtReg d = ToExtReg(sz, Vd, D);
|
const ExtReg d = ToExtReg(sz, Vd, D);
|
||||||
const size_t regs = sz ? imm8 >> 1 : imm8;
|
const size_t regs = sz ? imm8.ZeroExtend() >> 1 : imm8.ZeroExtend();
|
||||||
|
|
||||||
if (regs == 0 || RegNumber(d)+regs > 32) {
|
if (regs == 0 || RegNumber(d)+regs > 32) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -684,7 +684,7 @@ bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
auto address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(imm32));
|
auto address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(imm32));
|
||||||
ir.SetRegister(Reg::SP, address);
|
ir.SetRegister(Reg::SP, address);
|
||||||
|
|
||||||
|
@ -709,12 +709,12 @@ bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm
|
||||||
|
|
||||||
// VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
// VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||||
// VLDR<c> <Sd>, [<Rn>{, #+/-<imm>}]
|
// VLDR<c> <Sd>, [<Rn>{, #+/-<imm>}]
|
||||||
bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const auto d = ToExtReg(sz, Vd, D);
|
const auto d = ToExtReg(sz, Vd, D);
|
||||||
const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
|
const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
|
||||||
const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
|
const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
|
||||||
|
@ -735,12 +735,12 @@ bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd
|
||||||
|
|
||||||
// VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
// VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||||
// VSTR<c> <Sd>, [<Rn>{, #+/-<imm>}]
|
// VSTR<c> <Sd>, [<Rn>{, #+/-<imm>}]
|
||||||
bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8) {
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const auto d = ToExtReg(sz, Vd, D);
|
const auto d = ToExtReg(sz, Vd, D);
|
||||||
const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
|
const auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
|
||||||
const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
|
const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
|
||||||
|
@ -761,7 +761,7 @@ bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd
|
||||||
}
|
}
|
||||||
|
|
||||||
// VSTM{mode}<c> <Rn>{!}, <list of double registers>
|
// VSTM{mode}<c> <Rn>{!}, <list of double registers>
|
||||||
bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
if (!p && !u && !w) {
|
if (!p && !u && !w) {
|
||||||
ASSERT_MSG(false, "Decode error");
|
ASSERT_MSG(false, "Decode error");
|
||||||
}
|
}
|
||||||
|
@ -779,7 +779,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto d = ToExtReg(true, Vd, D);
|
const auto d = ToExtReg(true, Vd, D);
|
||||||
const size_t regs = imm8 / 2;
|
const size_t regs = imm8.ZeroExtend() / 2;
|
||||||
|
|
||||||
if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) {
|
if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -789,7 +789,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
||||||
if (w) {
|
if (w) {
|
||||||
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
||||||
|
@ -813,7 +813,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// VSTM{mode}<c> <Rn>{!}, <list of single registers>
|
// VSTM{mode}<c> <Rn>{!}, <list of single registers>
|
||||||
bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
if (!p && !u && !w) {
|
if (!p && !u && !w) {
|
||||||
ASSERT_MSG(false, "Decode error");
|
ASSERT_MSG(false, "Decode error");
|
||||||
}
|
}
|
||||||
|
@ -831,7 +831,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto d = ToExtReg(false, Vd, D);
|
const auto d = ToExtReg(false, Vd, D);
|
||||||
const size_t regs = imm8;
|
const size_t regs = imm8.ZeroExtend();
|
||||||
|
|
||||||
if (regs == 0 || A32::RegNumber(d)+regs > 32) {
|
if (regs == 0 || A32::RegNumber(d)+regs > 32) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -841,7 +841,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
||||||
if (w) {
|
if (w) {
|
||||||
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
||||||
|
@ -856,7 +856,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// VLDM{mode}<c> <Rn>{!}, <list of double registers>
|
// VLDM{mode}<c> <Rn>{!}, <list of double registers>
|
||||||
bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
if (!p && !u && !w) {
|
if (!p && !u && !w) {
|
||||||
ASSERT_MSG(false, "Decode error");
|
ASSERT_MSG(false, "Decode error");
|
||||||
}
|
}
|
||||||
|
@ -874,7 +874,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto d = ToExtReg(true, Vd, D);
|
const auto d = ToExtReg(true, Vd, D);
|
||||||
const size_t regs = imm8 / 2;
|
const size_t regs = imm8.ZeroExtend() / 2;
|
||||||
|
|
||||||
if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) {
|
if (regs == 0 || regs > 16 || A32::RegNumber(d)+regs > 32) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -884,7 +884,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
||||||
if (w) {
|
if (w) {
|
||||||
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
||||||
|
@ -906,7 +906,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// VLDM{mode}<c> <Rn>{!}, <list of single registers>
|
// VLDM{mode}<c> <Rn>{!}, <list of single registers>
|
||||||
bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm8 imm8) {
|
bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8) {
|
||||||
if (!p && !u && !w) {
|
if (!p && !u && !w) {
|
||||||
ASSERT_MSG(false, "Decode error");
|
ASSERT_MSG(false, "Decode error");
|
||||||
}
|
}
|
||||||
|
@ -924,7 +924,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto d = ToExtReg(false, Vd, D);
|
const auto d = ToExtReg(false, Vd, D);
|
||||||
const size_t regs = imm8;
|
const size_t regs = imm8.ZeroExtend();
|
||||||
|
|
||||||
if (regs == 0 || A32::RegNumber(d)+regs > 32) {
|
if (regs == 0 || A32::RegNumber(d)+regs > 32) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -934,7 +934,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
auto address = u ? ir.GetRegister(n) : IR::U32(ir.Sub(ir.GetRegister(n), ir.Imm32(imm32)));
|
||||||
if (w) {
|
if (w) {
|
||||||
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
|
#include "frontend/imm.h"
|
||||||
#include "frontend/A32/decoder/thumb16.h"
|
#include "frontend/A32/decoder/thumb16.h"
|
||||||
#include "frontend/A32/decoder/thumb32.h"
|
#include "frontend/A32/decoder/thumb32.h"
|
||||||
#include "frontend/A32/ir_emitter.h"
|
#include "frontend/A32/ir_emitter.h"
|
||||||
|
@ -39,8 +40,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LSLS <Rd>, <Rm>, #<imm5>
|
// LSLS <Rd>, <Rm>, #<imm5>
|
||||||
bool thumb16_LSL_imm(Imm5 imm5, Reg m, Reg d) {
|
bool thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||||
const u8 shift_n = imm5;
|
const u8 shift_n = imm5.ZeroExtend<u8>();
|
||||||
const auto cpsr_c = ir.GetCFlag();
|
const auto cpsr_c = ir.GetCFlag();
|
||||||
const auto result = ir.LogicalShiftLeft(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
|
const auto result = ir.LogicalShiftLeft(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
|
||||||
|
|
||||||
|
@ -52,8 +53,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LSRS <Rd>, <Rm>, #<imm5>
|
// LSRS <Rd>, <Rm>, #<imm5>
|
||||||
bool thumb16_LSR_imm(Imm5 imm5, Reg m, Reg d) {
|
bool thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||||
const u8 shift_n = imm5 != 0 ? imm5 : 32;
|
const u8 shift_n = imm5 != 0 ? imm5.ZeroExtend<u8>() : u8(32);
|
||||||
const auto cpsr_c = ir.GetCFlag();
|
const auto cpsr_c = ir.GetCFlag();
|
||||||
const auto result = ir.LogicalShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
|
const auto result = ir.LogicalShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
|
||||||
|
|
||||||
|
@ -65,8 +66,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASRS <Rd>, <Rm>, #<imm5>
|
// ASRS <Rd>, <Rm>, #<imm5>
|
||||||
bool thumb16_ASR_imm(Imm5 imm5, Reg m, Reg d) {
|
bool thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||||
const u8 shift_n = imm5 != 0 ? imm5 : 32;
|
const u8 shift_n = imm5 != 0 ? imm5.ZeroExtend<u8>() : u8(32);
|
||||||
const auto cpsr_c = ir.GetCFlag();
|
const auto cpsr_c = ir.GetCFlag();
|
||||||
const auto result = ir.ArithmeticShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
|
const auto result = ir.ArithmeticShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
|
||||||
|
|
||||||
|
@ -103,8 +104,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// ADDS <Rd>, <Rn>, #<imm3>
|
// ADDS <Rd>, <Rn>, #<imm3>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
bool thumb16_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) {
|
bool thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) {
|
||||||
const u32 imm32 = imm3 & 0x7;
|
const u32 imm32 = imm3.ZeroExtend();
|
||||||
const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
|
const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
|
||||||
|
|
||||||
ir.SetRegister(d, result.result);
|
ir.SetRegister(d, result.result);
|
||||||
|
@ -117,8 +118,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// SUBS <Rd>, <Rn>, #<imm3>
|
// SUBS <Rd>, <Rn>, #<imm3>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
bool thumb16_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) {
|
bool thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d) {
|
||||||
const u32 imm32 = imm3 & 0x7;
|
const u32 imm32 = imm3.ZeroExtend();
|
||||||
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
|
|
||||||
ir.SetRegister(d, result.result);
|
ir.SetRegister(d, result.result);
|
||||||
|
@ -131,8 +132,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// MOVS <Rd>, #<imm8>
|
// MOVS <Rd>, #<imm8>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
bool thumb16_MOV_imm(Reg d, Imm8 imm8) {
|
bool thumb16_MOV_imm(Reg d, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 & 0xFF;
|
const u32 imm32 = imm8.ZeroExtend();
|
||||||
const auto result = ir.Imm32(imm32);
|
const auto result = ir.Imm32(imm32);
|
||||||
|
|
||||||
ir.SetRegister(d, result);
|
ir.SetRegister(d, result);
|
||||||
|
@ -142,8 +143,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMP <Rn>, #<imm8>
|
// CMP <Rn>, #<imm8>
|
||||||
bool thumb16_CMP_imm(Reg n, Imm8 imm8) {
|
bool thumb16_CMP_imm(Reg n, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 & 0xFF;
|
const u32 imm32 = imm8.ZeroExtend();
|
||||||
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
|
|
||||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
@ -155,8 +156,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// ADDS <Rdn>, #<imm8>
|
// ADDS <Rdn>, #<imm8>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
bool thumb16_ADD_imm_t2(Reg d_n, Imm8 imm8) {
|
bool thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 & 0xFF;
|
const u32 imm32 = imm8.ZeroExtend();
|
||||||
const Reg d = d_n;
|
const Reg d = d_n;
|
||||||
const Reg n = d_n;
|
const Reg n = d_n;
|
||||||
const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
|
const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
|
||||||
|
@ -171,8 +172,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// SUBS <Rd>, <Rn>, #<imm3>
|
// SUBS <Rd>, <Rn>, #<imm3>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
bool thumb16_SUB_imm_t2(Reg d_n, Imm8 imm8) {
|
bool thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 & 0xFF;
|
const u32 imm32 = imm8.ZeroExtend();
|
||||||
const Reg d = d_n;
|
const Reg d = d_n;
|
||||||
const Reg n = d_n;
|
const Reg n = d_n;
|
||||||
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
|
@ -448,8 +449,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// LDR <Rt>, <label>
|
// LDR <Rt>, <label>
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_LDR_literal(Reg t, Imm8 imm8) {
|
bool thumb16_LDR_literal(Reg t, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const u32 address = ir.AlignPC(4) + imm32;
|
const u32 address = ir.AlignPC(4) + imm32;
|
||||||
const auto data = ir.ReadMemory32(ir.Imm32(address));
|
const auto data = ir.ReadMemory32(ir.Imm32(address));
|
||||||
|
|
||||||
|
@ -539,8 +540,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// STR <Rt>, [<Rn>, #<imm>]
|
// STR <Rt>, [<Rn>, #<imm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_STR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
|
||||||
const u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.GetRegister(t);
|
const auto data = ir.GetRegister(t);
|
||||||
|
|
||||||
|
@ -550,8 +551,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// LDR <Rt>, [<Rn>, #<imm>]
|
// LDR <Rt>, [<Rn>, #<imm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t) {
|
||||||
const u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.ReadMemory32(address);
|
const auto data = ir.ReadMemory32(address);
|
||||||
|
|
||||||
|
@ -561,8 +562,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// STRB <Rt>, [<Rn>, #<imm>]
|
// STRB <Rt>, [<Rn>, #<imm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_STRB_imm(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
const u32 imm32 = imm5;
|
const u32 imm32 = imm5.ZeroExtend();
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.LeastSignificantByte(ir.GetRegister(t));
|
const auto data = ir.LeastSignificantByte(ir.GetRegister(t));
|
||||||
|
|
||||||
|
@ -572,8 +573,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// LDRB <Rt>, [<Rn>, #<imm>]
|
// LDRB <Rt>, [<Rn>, #<imm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_LDRB_imm(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
const u32 imm32 = imm5;
|
const u32 imm32 = imm5.ZeroExtend();
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
|
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
|
||||||
|
|
||||||
|
@ -582,8 +583,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// STRH <Rt>, [<Rn>, #<imm5>]
|
// STRH <Rt>, [<Rn>, #<imm5>]
|
||||||
bool thumb16_STRH_imm(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
const u32 imm32 = imm5 << 1;
|
const u32 imm32 = imm5.ZeroExtend() << 1;
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.LeastSignificantHalf(ir.GetRegister(t));
|
const auto data = ir.LeastSignificantHalf(ir.GetRegister(t));
|
||||||
|
|
||||||
|
@ -592,8 +593,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDRH <Rt>, [<Rn>, #<imm5>]
|
// LDRH <Rt>, [<Rn>, #<imm5>]
|
||||||
bool thumb16_LDRH_imm(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t) {
|
||||||
const u32 imm32 = imm5 << 1;
|
const u32 imm32 = imm5.ZeroExtend() << 1;
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
|
||||||
|
|
||||||
|
@ -603,8 +604,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// STR <Rt>, [<Rn>, #<imm>]
|
// STR <Rt>, [<Rn>, #<imm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_STR_imm_t2(Reg t, Imm5 imm5) {
|
bool thumb16_STR_imm_t2(Reg t, Imm<5> imm5) {
|
||||||
const u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
const Reg n = Reg::SP;
|
const Reg n = Reg::SP;
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.GetRegister(t);
|
const auto data = ir.GetRegister(t);
|
||||||
|
@ -615,8 +616,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// LDR <Rt>, [<Rn>, #<imm>]
|
// LDR <Rt>, [<Rn>, #<imm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
bool thumb16_LDR_imm_t2(Reg t, Imm5 imm5) {
|
bool thumb16_LDR_imm_t2(Reg t, Imm<5> imm5) {
|
||||||
const u32 imm32 = imm5 << 2;
|
const u32 imm32 = imm5.ZeroExtend() << 2;
|
||||||
const Reg n = Reg::SP;
|
const Reg n = Reg::SP;
|
||||||
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||||
const auto data = ir.ReadMemory32(address);
|
const auto data = ir.ReadMemory32(address);
|
||||||
|
@ -627,8 +628,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
|
|
||||||
// ADR <Rd>, <label>
|
// ADR <Rd>, <label>
|
||||||
// Rd cannot encode R15.
|
// Rd cannot encode R15.
|
||||||
bool thumb16_ADR(Reg d, Imm8 imm8) {
|
bool thumb16_ADR(Reg d, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const auto result = ir.Imm32(ir.AlignPC(4) + imm32);
|
const auto result = ir.Imm32(ir.AlignPC(4) + imm32);
|
||||||
|
|
||||||
ir.SetRegister(d, result);
|
ir.SetRegister(d, result);
|
||||||
|
@ -636,8 +637,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD <Rd>, SP, #<imm>
|
// ADD <Rd>, SP, #<imm>
|
||||||
bool thumb16_ADD_sp_t1(Reg d, Imm8 imm8) {
|
bool thumb16_ADD_sp_t1(Reg d, Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8 << 2;
|
const u32 imm32 = imm8.ZeroExtend() << 2;
|
||||||
const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0));
|
const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0));
|
||||||
|
|
||||||
ir.SetRegister(d, result.result);
|
ir.SetRegister(d, result.result);
|
||||||
|
@ -645,8 +646,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD SP, SP, #<imm>
|
// ADD SP, SP, #<imm>
|
||||||
bool thumb16_ADD_sp_t2(Imm7 imm7) {
|
bool thumb16_ADD_sp_t2(Imm<7> imm7) {
|
||||||
const u32 imm32 = imm7 << 2;
|
const u32 imm32 = imm7.ZeroExtend() << 2;
|
||||||
const Reg d = Reg::SP;
|
const Reg d = Reg::SP;
|
||||||
const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0));
|
const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0));
|
||||||
|
|
||||||
|
@ -655,8 +656,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUB SP, SP, #<imm>
|
// SUB SP, SP, #<imm>
|
||||||
bool thumb16_SUB_sp(Imm7 imm7) {
|
bool thumb16_SUB_sp(Imm<7> imm7) {
|
||||||
const u32 imm32 = imm7 << 2;
|
const u32 imm32 = imm7.ZeroExtend() << 2;
|
||||||
const Reg d = Reg::SP;
|
const Reg d = Reg::SP;
|
||||||
const auto result = ir.SubWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(1));
|
const auto result = ir.SubWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
|
|
||||||
|
@ -861,8 +862,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SVC #<imm8>
|
// SVC #<imm8>
|
||||||
bool thumb16_SVC(Imm8 imm8) {
|
bool thumb16_SVC(Imm<8> imm8) {
|
||||||
const u32 imm32 = imm8;
|
const u32 imm32 = imm8.ZeroExtend();
|
||||||
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2));
|
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2));
|
||||||
ir.PushRSB(ir.current_location.AdvancePC(2));
|
ir.PushRSB(ir.current_location.AdvancePC(2));
|
||||||
ir.CallSupervisor(ir.Imm32(imm32));
|
ir.CallSupervisor(ir.Imm32(imm32));
|
||||||
|
@ -871,12 +872,12 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// B<cond> <label>
|
// B<cond> <label>
|
||||||
bool thumb16_B_t1(Cond cond, Imm8 imm8) {
|
bool thumb16_B_t1(Cond cond, Imm<8> imm8) {
|
||||||
if (cond == Cond::AL) {
|
if (cond == Cond::AL) {
|
||||||
return thumb16_UDF();
|
return thumb16_UDF();
|
||||||
}
|
}
|
||||||
|
|
||||||
const s32 imm32 = Common::SignExtend<9, s32>(imm8 << 1) + 4;
|
const s32 imm32 = static_cast<s32>((imm8.SignExtend<u32>() << 1) + 4);
|
||||||
const auto then_location = ir.current_location.AdvancePC(imm32);
|
const auto then_location = ir.current_location.AdvancePC(imm32);
|
||||||
const auto else_location = ir.current_location.AdvancePC(2);
|
const auto else_location = ir.current_location.AdvancePC(2);
|
||||||
|
|
||||||
|
@ -885,8 +886,8 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// B <label>
|
// B <label>
|
||||||
bool thumb16_B_t2(Imm11 imm11) {
|
bool thumb16_B_t2(Imm<11> imm11) {
|
||||||
const s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4;
|
const s32 imm32 = static_cast<s32>((imm11.SignExtend<u32>() << 1) + 4);
|
||||||
const auto next_location = ir.current_location.AdvancePC(imm32);
|
const auto next_location = ir.current_location.AdvancePC(imm32);
|
||||||
|
|
||||||
ir.SetTerm(IR::Term::LinkBlock{next_location});
|
ir.SetTerm(IR::Term::LinkBlock{next_location});
|
||||||
|
@ -894,26 +895,26 @@ struct ThumbTranslatorVisitor final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BL <label>
|
// BL <label>
|
||||||
bool thumb32_BL_imm(Imm11 hi, Imm11 lo) {
|
bool thumb32_BL_imm(Imm<11> hi, Imm<11> lo) {
|
||||||
ir.PushRSB(ir.current_location.AdvancePC(4));
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
|
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
|
||||||
|
|
||||||
const s32 imm32 = Common::SignExtend<23, s32>((hi << 12) | (lo << 1)) + 4;
|
const s32 imm32 = static_cast<s32>((concatenate(hi, lo).SignExtend<u32>() << 1) + 4);
|
||||||
const auto new_location = ir.current_location.AdvancePC(imm32);
|
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BLX <label>
|
// BLX <label>
|
||||||
bool thumb32_BLX_imm(Imm11 hi, Imm11 lo) {
|
bool thumb32_BLX_imm(Imm<11> hi, Imm<11> lo) {
|
||||||
if ((lo & 1) != 0) {
|
if (lo.Bit<0>()) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.PushRSB(ir.current_location.AdvancePC(4));
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
|
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
|
||||||
|
|
||||||
const s32 imm32 = Common::SignExtend<23, s32>((hi << 12) | (lo << 1));
|
const s32 imm32 = static_cast<s32>(concatenate(hi, lo).SignExtend<u32>() << 1);
|
||||||
const auto new_location = ir.current_location
|
const auto new_location = ir.current_location
|
||||||
.SetPC(ir.AlignPC(4) + imm32)
|
.SetPC(ir.AlignPC(4) + imm32)
|
||||||
.SetTFlag(false);
|
.SetTFlag(false);
|
||||||
|
|
|
@ -39,14 +39,6 @@ enum class ExtReg {
|
||||||
D24, D25, D26, D27, D28, D29, D30, D31,
|
D24, D25, D26, D27, D28, D29, D30, D31,
|
||||||
};
|
};
|
||||||
|
|
||||||
using Imm3 = u8;
|
|
||||||
using Imm4 = u8;
|
|
||||||
using Imm5 = u8;
|
|
||||||
using Imm7 = u8;
|
|
||||||
using Imm8 = u8;
|
|
||||||
using Imm11 = u16;
|
|
||||||
using Imm12 = u16;
|
|
||||||
using Imm24 = u32;
|
|
||||||
using RegList = u16;
|
using RegList = u16;
|
||||||
|
|
||||||
enum class ShiftType {
|
enum class ShiftType {
|
||||||
|
|
Loading…
Reference in a new issue