Merged in bunnei/dynarmic/load_store (pull request #9)
arm: Implement LDR/LDRB/LDRH/LDRD/STR/STRB/STRH/STRD.
This commit is contained in:
commit
cd1eef2801
4 changed files with 274 additions and 33 deletions
|
@ -177,16 +177,16 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
//INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
//INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
//INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"),
|
//INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"),
|
//INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
|
INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
|
||||||
//INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
|
INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
|
||||||
//INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
|
INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
|
||||||
//INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"),
|
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_imm, "LDRSB (imm)", "cccc000pu1w1nnnnddddvvvv1101vvvv"),
|
||||||
|
@ -199,16 +199,16 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
//INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
|
//INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
|
||||||
//INST(&V::arm_LDRT, "LDRT (A1)", "cccc0100u011nnnnttttvvvvvvvvvvvv"),
|
//INST(&V::arm_LDRT, "LDRT (A1)", "cccc0100u011nnnnttttvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_LDRT, "LDRT (A2)", "cccc0110u011nnnnttttvvvvvrr0mmmm"),
|
//INST(&V::arm_LDRT, "LDRT (A2)", "cccc0110u011nnnnttttvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"),
|
//INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"),
|
//INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
|
INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
|
||||||
//INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
|
INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
|
||||||
//INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"),
|
INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"),
|
||||||
//INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"),
|
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)", "cccc0100u010nnnnttttvvvvvvvvvvvv"),
|
//INST(&V::arm_STRT, "STRT (A1)", "cccc0100u010nnnnttttvvvvvvvvvvvv"),
|
||||||
|
|
|
@ -53,13 +53,17 @@ bool ArmTranslatorVisitor::ConditionPassed(Cond cond) {
|
||||||
"(i.e.: one and only one conditional instruction per block)");
|
"(i.e.: one and only one conditional instruction per block)");
|
||||||
ASSERT_MSG(cond_state != ConditionalState::Break,
|
ASSERT_MSG(cond_state != ConditionalState::Break,
|
||||||
"This should never happen. We requested a break but that wasn't honored.");
|
"This should never happen. We requested a break but that wasn't honored.");
|
||||||
ASSERT_MSG(cond != Cond::NV, "NV conditional is obsolete");
|
|
||||||
|
|
||||||
if (cond == Cond::AL) {
|
if (cond == Cond::AL) {
|
||||||
// Everything is fine with the world
|
// Everything is fine with the world
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cond == Cond::NV) {
|
||||||
|
// NV conditional is obsolete, but still seems to be used in some places!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// non-AL cond
|
// non-AL cond
|
||||||
|
|
||||||
if (!ir.block.instructions.empty()) {
|
if (!ir.block.instructions.empty()) {
|
||||||
|
|
|
@ -9,20 +9,99 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Arm {
|
namespace Arm {
|
||||||
|
|
||||||
|
static IR::Value GetAddressingMode(IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value index) {
|
||||||
|
IR::Value address;
|
||||||
|
if (P) {
|
||||||
|
// Pre-indexed addressing
|
||||||
|
if (n == Reg::PC && index.IsImmediate()) {
|
||||||
|
address = U ? ir.Imm32(ir.AlignPC(4) + index.GetU32()) : ir.Imm32(ir.AlignPC(4) - index.GetU32());
|
||||||
|
} else {
|
||||||
|
address = U ? ir.Add(ir.GetRegister(n), index) : ir.Sub(ir.GetRegister(n), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrote calculated address back to the base register
|
||||||
|
if (W) {
|
||||||
|
ir.SetRegister(n, address);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Post-indexed addressing
|
||||||
|
address = (n == Reg::PC) ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
|
||||||
|
|
||||||
|
if (U) {
|
||||||
|
ir.SetRegister(n, ir.Add(ir.GetRegister(n), index));
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(n, ir.Sub(ir.GetRegister(n), index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bunnei): Handle W=1 mode, which in this scenario does an unprivileged (User mode) access.
|
||||||
|
}
|
||||||
|
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_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.BXWritePC(data);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, shifted.result));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.BXWritePC(data);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12))));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
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)));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRBT() {
|
bool ArmTranslatorVisitor::arm_LDRBT() {
|
||||||
|
@ -30,19 +109,111 @@ bool ArmTranslatorVisitor::arm_LDRBT() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
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));
|
||||||
|
auto data_a = ir.ReadMemory32(address_a);
|
||||||
|
auto data_b = ir.ReadMemory32(address_b);
|
||||||
|
|
||||||
|
switch(d) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.ALUWritePC(data_a);
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(d, data_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
|
||||||
|
if (reg_b == Reg::PC) {
|
||||||
|
ir.ALUWritePC(data_b);
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(reg_b, data_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == Reg::PC || reg_b == Reg::PC) {
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m));
|
||||||
|
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(d) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.ALUWritePC(data_a);
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(d, data_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
|
||||||
|
if (reg_b == Reg::PC) {
|
||||||
|
ir.ALUWritePC(data_b);
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(reg_b, data_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == Reg::PC || reg_b == Reg::PC) {
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.ALUWritePC(ir.Add(data, ir.Imm32(4)));
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRHT() {
|
bool ArmTranslatorVisitor::arm_LDRHT() {
|
||||||
|
@ -78,19 +249,43 @@ bool ArmTranslatorVisitor::arm_LDRT() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12));
|
||||||
|
ir.WriteMemory32(address, ir.GetRegister(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
const auto address = GetAddressingMode(ir, P, U, W, n, shifted.result);
|
||||||
|
ir.WriteMemory32(address, ir.GetRegister(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12));
|
||||||
|
const auto value = (d == Reg::PC) ? ir.Imm8(ir.PC() - 8) : ir.GetRegister(d);
|
||||||
|
ir.WriteMemory8(address, ir.LeastSignificantByte(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
const auto address = GetAddressingMode(ir, P, U, W, n, shifted.result);
|
||||||
|
const auto value = (d == Reg::PC) ? ir.Imm8(ir.PC() - 8) : ir.GetRegister(d);
|
||||||
|
ir.WriteMemory8(address, ir.LeastSignificantByte(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRBT() {
|
bool ArmTranslatorVisitor::arm_STRBT() {
|
||||||
|
@ -98,19 +293,51 @@ bool ArmTranslatorVisitor::arm_STRBT() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
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 value_a = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d);
|
||||||
|
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
|
||||||
|
const auto value_b = (reg_b == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(reg_b);
|
||||||
|
ir.WriteMemory32(address_a, value_a);
|
||||||
|
ir.WriteMemory32(address_b, value_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
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 value_a = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d);
|
||||||
|
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
|
||||||
|
const auto value_b = (reg_b == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(reg_b);
|
||||||
|
ir.WriteMemory32(address_a, value_a);
|
||||||
|
ir.WriteMemory32(address_b, value_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b));
|
||||||
|
const auto value = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d);
|
||||||
|
ir.WriteMemory16(address, ir.LeastSignificantHalf(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto address = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m));
|
||||||
|
const auto value = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d);
|
||||||
|
ir.WriteMemory16(address, ir.LeastSignificantHalf(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_STRHT() {
|
bool ArmTranslatorVisitor::arm_STRHT() {
|
||||||
|
|
|
@ -248,6 +248,16 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
|
||||||
}
|
}
|
||||||
printf("CPSR: %08x %08x %s\n", interp.Cpsr, jit.Cpsr(), interp.Cpsr != jit.Cpsr() ? "*" : "");
|
printf("CPSR: %08x %08x %s\n", interp.Cpsr, jit.Cpsr(), interp.Cpsr != jit.Cpsr() ? "*" : "");
|
||||||
|
|
||||||
|
printf("\nInterp Write Records:\n");
|
||||||
|
for (auto& record : interp_write_records) {
|
||||||
|
printf("%zu [%x] = %llx" PRIu64 "\n", record.size, record.address, record.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nJIT Write Records:\n");
|
||||||
|
for (auto& record : jit_write_records) {
|
||||||
|
printf("%zu [%x] = %llx" PRIu64 "\n", record.size, record.address, record.data);
|
||||||
|
}
|
||||||
|
|
||||||
Dynarmic::Arm::LocationDescriptor descriptor = {0, false, false, 0};
|
Dynarmic::Arm::LocationDescriptor descriptor = {0, false, false, 0};
|
||||||
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate(descriptor, &MemoryRead32);
|
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate(descriptor, &MemoryRead32);
|
||||||
Dynarmic::Optimization::GetSetElimination(ir_block);
|
Dynarmic::Optimization::GetSetElimination(ir_block);
|
||||||
|
|
Loading…
Reference in a new issue