translate_arm/load_store: Handle unpredictable instructions
This necessated handling literal versions of the instructions separately as they had different requirements. The rationale for detecting unpredictable instructions is because: a. they are unlikely to be outputted by a well-behaved compiler b. their behaviour may change between different processors I would rather unpredictable instructions fail loudly than silently do approximately the right thing.
This commit is contained in:
parent
5869e79b9c
commit
4acc481463
5 changed files with 376 additions and 107 deletions
|
@ -185,42 +185,48 @@ std::vector<ArmMatcher<V>> GetArmDecodeTable() {
|
||||||
INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu"), // v2S (v6: Deprecated)
|
INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu"), // v2S (v6: Deprecated)
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
|
||||||
INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
|
||||||
INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
|
||||||
INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
|
|
||||||
INST(&V::arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------"),
|
INST(&V::arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------"),
|
||||||
INST(&V::arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----"),
|
INST(&V::arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----"),
|
||||||
INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
|
|
||||||
INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
|
|
||||||
INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
|
|
||||||
INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"),
|
|
||||||
INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"),
|
INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"),
|
||||||
INST(&V::arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----"),
|
INST(&V::arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----"),
|
||||||
INST(&V::arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnddddvvvv1101vvvv"),
|
|
||||||
INST(&V::arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnndddd00001101mmmm"),
|
|
||||||
INST(&V::arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----"),
|
INST(&V::arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----"),
|
||||||
INST(&V::arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----"),
|
INST(&V::arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----"),
|
||||||
INST(&V::arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnddddvvvv1111vvvv"),
|
|
||||||
INST(&V::arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnndddd00001111mmmm"),
|
|
||||||
INST(&V::arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----"),
|
INST(&V::arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----"),
|
||||||
INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
|
INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
|
||||||
INST(&V::arm_LDRT, "LDRT (A1)", "----0100-011--------------------"),
|
INST(&V::arm_LDRT, "LDRT (A1)", "----0100-011--------------------"),
|
||||||
INST(&V::arm_LDRT, "LDRT (A2)", "----0110-011---------------0----"),
|
INST(&V::arm_LDRT, "LDRT (A2)", "----0110-011---------------0----"),
|
||||||
INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
|
|
||||||
INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
|
|
||||||
INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
|
|
||||||
INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
|
|
||||||
INST(&V::arm_STRBT, "STRBT (A1)", "----0100-110--------------------"),
|
INST(&V::arm_STRBT, "STRBT (A1)", "----0100-110--------------------"),
|
||||||
INST(&V::arm_STRBT, "STRBT (A2)", "----0110-110---------------0----"),
|
INST(&V::arm_STRBT, "STRBT (A2)", "----0110-110---------------0----"),
|
||||||
INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
|
|
||||||
INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
|
|
||||||
INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"),
|
|
||||||
INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"),
|
|
||||||
INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"),
|
INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"),
|
||||||
INST(&V::arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----"),
|
INST(&V::arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----"),
|
||||||
INST(&V::arm_STRT, "STRT (A1)", "----0100-010--------------------"),
|
INST(&V::arm_STRT, "STRT (A1)", "----0100-010--------------------"),
|
||||||
INST(&V::arm_STRT, "STRT (A2)", "----0110-010---------------0----"),
|
INST(&V::arm_STRT, "STRT (A2)", "----0110-010---------------0----"),
|
||||||
|
INST(&V::arm_LDR_lit, "LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv"),
|
||||||
|
INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv"),
|
||||||
|
INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm"),
|
||||||
|
INST(&V::arm_LDRB_lit, "LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv"),
|
||||||
|
INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv"),
|
||||||
|
INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm"),
|
||||||
|
INST(&V::arm_LDRD_lit, "LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv"),
|
||||||
|
INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv"), // v5E
|
||||||
|
INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm"), // v5E
|
||||||
|
INST(&V::arm_LDRH_lit, "LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv"),
|
||||||
|
INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv"),
|
||||||
|
INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm"),
|
||||||
|
INST(&V::arm_LDRSB_lit, "LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv"),
|
||||||
|
INST(&V::arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv"),
|
||||||
|
INST(&V::arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm"),
|
||||||
|
INST(&V::arm_LDRSH_lit, "LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv"),
|
||||||
|
INST(&V::arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv"),
|
||||||
|
INST(&V::arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm"),
|
||||||
|
INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv"),
|
||||||
|
INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm"),
|
||||||
|
INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv"),
|
||||||
|
INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm"),
|
||||||
|
INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv"), // v5E
|
||||||
|
INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm"), // v5E
|
||||||
|
INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv"),
|
||||||
|
INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm"),
|
||||||
|
|
||||||
// Load/Store Multiple instructions
|
// Load/Store Multiple instructions
|
||||||
INST(&V::arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx"), // all
|
INST(&V::arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||||
|
|
|
@ -337,6 +337,10 @@ 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) {
|
||||||
|
bool P = true, W = false;
|
||||||
|
return arm_LDR_imm(cond, P, U, W, Reg::PC, t, imm12);
|
||||||
|
}
|
||||||
std::string arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
std::string arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
||||||
if (P) {
|
if (P) {
|
||||||
return Common::StringFromFormat("ldr%s %s, [%s, #%c%u]%s", CondToString(cond), RegToString(t), RegToString(n), U ? '+' : '-', imm12, W ? "!" : "");
|
return Common::StringFromFormat("ldr%s %s, [%s, #%c%u]%s", CondToString(cond), RegToString(t), RegToString(n), U ? '+' : '-', imm12, W ? "!" : "");
|
||||||
|
@ -351,6 +355,10 @@ public:
|
||||||
return Common::StringFromFormat("ldr%s %s, [%s], %c%s%s%s", CondToString(cond), RegToString(t), RegToString(n), U ? '+' : '-', RegToString(m), ShiftStr(shift, imm5).c_str(), W ? " (err: W == 1!!!)" : "");
|
return Common::StringFromFormat("ldr%s %s, [%s], %c%s%s%s", CondToString(cond), RegToString(t), RegToString(n), U ? '+' : '-', RegToString(m), ShiftStr(shift, imm5).c_str(), W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
||||||
|
bool P = true, W = false;
|
||||||
|
return arm_LDRB_imm(cond, P, U, W, Reg::PC, t, imm12);
|
||||||
|
}
|
||||||
std::string arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
std::string arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
||||||
if (P) {
|
if (P) {
|
||||||
return Common::StringFromFormat("ldrb%s %s, [%s, #%c%u]%s", CondToString(cond), RegToString(t), RegToString(n), U ? '+' : '-', imm12, W ? "!" : "");
|
return Common::StringFromFormat("ldrb%s %s, [%s, #%c%u]%s", CondToString(cond), RegToString(t), RegToString(n), U ? '+' : '-', imm12, W ? "!" : "");
|
||||||
|
@ -366,6 +374,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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) {
|
||||||
|
bool P = true, W = false;
|
||||||
|
return arm_LDRD_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
|
}
|
||||||
std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
u32 imm32 = (imm8a << 4) | imm8b;
|
||||||
if (P) {
|
if (P) {
|
||||||
|
@ -381,6 +393,9 @@ public:
|
||||||
return Common::StringFromFormat("ldrd%s %s, %s, [%s], %c%s%s", CondToString(cond), RegToString(t), RegToString(t+1), RegToString(n), U ? '+' : '-', RegToString(m), W ? " (err: W == 1!!!)" : "");
|
return Common::StringFromFormat("ldrd%s %s, %s, [%s], %c%s%s", CondToString(cond), RegToString(t), RegToString(t+1), RegToString(n), U ? '+' : '-', RegToString(m), W ? " (err: W == 1!!!)" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 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, Imm4 imm8a, Imm4 imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
u32 imm32 = (imm8a << 4) | imm8b;
|
||||||
if (P) {
|
if (P) {
|
||||||
|
@ -397,6 +412,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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) {
|
||||||
|
bool P = true, W = false;
|
||||||
|
return arm_LDRSB_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
|
}
|
||||||
std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
u32 imm32 = (imm8a << 4) | imm8b;
|
||||||
if (P) {
|
if (P) {
|
||||||
|
@ -413,6 +432,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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) {
|
||||||
|
bool P = true, W = false;
|
||||||
|
return arm_LDRSH_imm(cond, P, U, W, Reg::PC, t, imm8a, imm8b);
|
||||||
|
}
|
||||||
std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
std::string arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
u32 imm32 = (imm8a << 4) | imm8b;
|
u32 imm32 = (imm8a << 4) | imm8b;
|
||||||
if (P) {
|
if (P) {
|
||||||
|
|
|
@ -9,6 +9,38 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Arm {
|
namespace Arm {
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRBT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRHT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRSBT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRSHT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_STRBT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_STRHT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_STRT() {
|
||||||
|
ASSERT_MSG(false, "System instructions unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
static IR::Value GetAddressingMode(IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value index) {
|
static IR::Value GetAddressingMode(IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value index) {
|
||||||
IR::Value address;
|
IR::Value address;
|
||||||
if (P) {
|
if (P) {
|
||||||
|
@ -38,11 +70,35 @@ static IR::Value GetAddressingMode(IREmitter& ir, bool P, bool U, bool W, Reg n,
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
||||||
|
bool P = true, W = false;
|
||||||
|
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, Reg::PC, ir.Imm32(imm12)));
|
||||||
|
|
||||||
|
if (t == Reg::PC) {
|
||||||
|
ir.BXWritePC(data);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(t, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
||||||
|
if (n == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if ((!P || W) && n == t)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)));
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.BXWritePC(data);
|
ir.BXWritePC(data);
|
||||||
if (!P && W && n == Reg::R13)
|
if (!P && W && n == Reg::R13)
|
||||||
ir.SetTerm(IR::Term::PopRSBHint{});
|
ir.SetTerm(IR::Term::PopRSBHint{});
|
||||||
|
@ -51,74 +107,167 @@ bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if (m == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == Reg::PC || n == t))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, shifted.result));
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, shifted.result));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.BXWritePC(data);
|
ir.BXWritePC(data);
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) {
|
||||||
if (ConditionPassed(cond)) {
|
if (t == Reg::PC)
|
||||||
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12))));
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
bool P = true, W = false;
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, Reg::PC, ir.Imm32(imm12))));
|
||||||
|
|
||||||
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) {
|
||||||
|
if (n == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if ((!P || W) && n == t)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12))));
|
||||||
|
|
||||||
|
if (t == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(t, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if (t == Reg::PC || m == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == Reg::PC || n == t))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, shifted.result)));
|
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, shifted.result)));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRBT() {
|
bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
return InterpretThisInstruction();
|
if (RegNumber(t) % 2 == 1)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t+1 == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
bool P = true, W = false;
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto address_a = GetAddressingMode(ir, P, U, W, Reg::PC, ir.Imm32(imm8a << 4 | imm8b));
|
||||||
|
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
||||||
|
auto data_a = ir.ReadMemory32(address_a);
|
||||||
|
auto data_b = ir.ReadMemory32(address_b);
|
||||||
|
|
||||||
|
switch (t) {
|
||||||
|
case Reg::PC:
|
||||||
|
data_a = ir.Add(data_a, ir.Imm32(4));
|
||||||
|
break;
|
||||||
|
case Reg::LR:
|
||||||
|
data_b = ir.Add(data_b, ir.Imm32(4));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
if (t == Reg::PC) {
|
||||||
|
ir.ALUWritePC(data_a);
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(t, data_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Reg reg_b = static_cast<Reg>(std::min(t + 1, Reg::R15));
|
||||||
|
if (reg_b == Reg::PC) {
|
||||||
|
ir.ALUWritePC(data_b);
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(reg_b, data_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == Reg::PC || reg_b == Reg::PC) {
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
|
if (n == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (RegNumber(t) % 2 == 1)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (!P && W)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == t || n == t+1))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t+1 == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b));
|
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b));
|
||||||
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
||||||
auto data_a = ir.ReadMemory32(address_a);
|
auto data_a = ir.ReadMemory32(address_a);
|
||||||
auto data_b = ir.ReadMemory32(address_b);
|
auto data_b = ir.ReadMemory32(address_b);
|
||||||
|
|
||||||
switch (d) {
|
switch (t) {
|
||||||
case Reg::PC:
|
case Reg::PC:
|
||||||
data_a = ir.Add(data_a, ir.Imm32(4));
|
data_a = ir.Add(data_a, ir.Imm32(4));
|
||||||
break;
|
break;
|
||||||
|
@ -129,20 +278,20 @@ bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(data_a);
|
ir.ALUWritePC(data_a);
|
||||||
} else {
|
} else {
|
||||||
ir.SetRegister(d, data_a);
|
ir.SetRegister(t, data_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
|
const Reg reg_b = static_cast<Reg>(std::min(t + 1, Reg::R15));
|
||||||
if (reg_b == Reg::PC) {
|
if (reg_b == Reg::PC) {
|
||||||
ir.ALUWritePC(data_b);
|
ir.ALUWritePC(data_b);
|
||||||
} else {
|
} else {
|
||||||
ir.SetRegister(reg_b, data_b);
|
ir.SetRegister(reg_b, data_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == Reg::PC || reg_b == Reg::PC) {
|
if (t == Reg::PC || reg_b == Reg::PC) {
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -151,14 +300,23 @@ bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
if (RegNumber(t) % 2 == 1)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (!P && W)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t+1 == Reg::PC || m == Reg::PC || m == t || m == t+1)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == Reg::PC || n == t || n == t+1))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m));
|
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m));
|
||||||
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
const auto address_b = ir.Add(address_a, ir.Imm32(4));
|
||||||
auto data_a = ir.ReadMemory32(address_a);
|
auto data_a = ir.ReadMemory32(address_a);
|
||||||
auto data_b = ir.ReadMemory32(address_b);
|
auto data_b = ir.ReadMemory32(address_b);
|
||||||
|
|
||||||
switch (d) {
|
switch (t) {
|
||||||
case Reg::PC:
|
case Reg::PC:
|
||||||
data_a = ir.Add(data_a, ir.Imm32(4));
|
data_a = ir.Add(data_a, ir.Imm32(4));
|
||||||
break;
|
break;
|
||||||
|
@ -169,20 +327,20 @@ bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(data_a);
|
ir.ALUWritePC(data_a);
|
||||||
} else {
|
} else {
|
||||||
ir.SetRegister(d, data_a);
|
ir.SetRegister(t, data_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
|
const Reg reg_b = static_cast<Reg>(std::min(t + 1, Reg::R15));
|
||||||
if (reg_b == Reg::PC) {
|
if (reg_b == Reg::PC) {
|
||||||
ir.ALUWritePC(data_b);
|
ir.ALUWritePC(data_b);
|
||||||
} else {
|
} else {
|
||||||
ir.SetRegister(reg_b, data_b);
|
ir.SetRegister(reg_b, data_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == Reg::PC || reg_b == Reg::PC) {
|
if (t == Reg::PC || reg_b == Reg::PC) {
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -191,118 +349,206 @@ bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if (P == W)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, Reg::PC, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
|
if (t == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(t, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
|
if (n == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if ((!P || W) && n == t)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if (t == Reg::PC || m == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == Reg::PC || n == t))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRHT() {
|
bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
return InterpretThisInstruction();
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
bool P = true, W = false;
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, Reg::PC, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
|
if (t == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
ir.SetRegister(t, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
|
if (n == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if ((!P || W) && n == t)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if (t == Reg::PC || m == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == Reg::PC || n == t))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRSBT() {
|
bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
return InterpretThisInstruction();
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
bool P = true, W = false;
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, Reg::PC, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
|
if (t == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
ir.SetRegister(t, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) {
|
||||||
|
if (n == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if ((!P || W) && n == t)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) {
|
||||||
|
ASSERT_MSG(!(!P && W), "T form of instruction unimplemented");
|
||||||
|
if (t == Reg::PC || m == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if ((!P || W) && (n == Reg::PC || n == t))
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (t == Reg::PC) {
|
||||||
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir.SetRegister(d, data);
|
ir.SetRegister(t, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRSHT() {
|
|
||||||
return InterpretThisInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRT() {
|
|
||||||
return InterpretThisInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12));
|
const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12));
|
||||||
|
@ -343,10 +589,6 @@ bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRBT() {
|
|
||||||
return InterpretThisInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b));
|
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b));
|
||||||
|
@ -395,14 +637,6 @@ bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRHT() {
|
|
||||||
return InterpretThisInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRT() {
|
|
||||||
return InterpretThisInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool LDMHelper(IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) {
|
static bool LDMHelper(IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) {
|
||||||
auto address = start_address;
|
auto address = start_address;
|
||||||
for (size_t i = 0; i <= 14; i++) {
|
for (size_t i = 0; i <= 14; i++) {
|
||||||
|
|
|
@ -155,35 +155,41 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_WFI() { return true; }
|
bool arm_WFI() { return true; }
|
||||||
bool arm_YIELD() { return true; }
|
bool arm_YIELD() { return true; }
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store
|
||||||
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
|
||||||
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
|
||||||
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
|
||||||
bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
|
||||||
bool arm_LDRBT();
|
bool arm_LDRBT();
|
||||||
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
|
||||||
bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
|
||||||
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
|
||||||
bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
|
||||||
bool arm_LDRHT();
|
bool arm_LDRHT();
|
||||||
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
|
||||||
bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
|
||||||
bool arm_LDRSBT();
|
bool arm_LDRSBT();
|
||||||
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
|
||||||
bool arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
|
||||||
bool arm_LDRSHT();
|
bool arm_LDRSHT();
|
||||||
bool arm_LDRT();
|
bool arm_LDRT();
|
||||||
|
bool arm_STRBT();
|
||||||
|
bool arm_STRHT();
|
||||||
|
bool arm_STRT();
|
||||||
|
bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12);
|
||||||
|
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
||||||
|
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12);
|
||||||
|
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12);
|
||||||
|
bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
|
bool arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b);
|
||||||
|
bool arm_LDRSH_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 d, Imm12 imm12);
|
bool arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
||||||
bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
||||||
bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
bool arm_STRBT();
|
|
||||||
bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
||||||
bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b);
|
||||||
bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
bool arm_STRHT();
|
|
||||||
bool arm_STRT();
|
|
||||||
|
|
||||||
// Load/Store multiple instructions
|
// Load/Store multiple instructions
|
||||||
bool arm_LDM(Cond cond, bool W, Reg n, RegList list);
|
bool arm_LDM(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
|
|
@ -643,7 +643,7 @@ TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]"
|
||||||
u32 rand = RandInt<u32>(0, 0xFF);
|
u32 rand = RandInt<u32>(0, 0xFF);
|
||||||
u32 Rm = RandInt<u32>(0, 14);
|
u32 Rm = RandInt<u32>(0, 14);
|
||||||
|
|
||||||
if (W) {
|
if (!P || W) {
|
||||||
while (Rn == Rd) {
|
while (Rn == Rd) {
|
||||||
Rn = RandInt<u32>(0, 14);
|
Rn = RandInt<u32>(0, 14);
|
||||||
Rd = RandInt<u32>(0, 14);
|
Rd = RandInt<u32>(0, 14);
|
||||||
|
|
Loading…
Reference in a new issue