A32: ARMv8: Implement LDA{,EX}{,B,D,H} and STL{,EX}{,B,D,H}
This commit is contained in:
parent
8808b8c479
commit
e7f1a0d408
5 changed files with 372 additions and 61 deletions
|
@ -106,16 +106,30 @@ INST(arm_NOP, "Reserved Hint", "----001100100000111100000000----
|
||||||
|
|
||||||
// Synchronization Primitive instructions
|
// Synchronization Primitive instructions
|
||||||
INST(arm_CLREX, "CLREX", "11110101011111111111000000011111") // v6K
|
INST(arm_CLREX, "CLREX", "11110101011111111111000000011111") // v6K
|
||||||
INST(arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111") // v6
|
|
||||||
INST(arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111") // v6K
|
|
||||||
INST(arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111") // v6K
|
|
||||||
INST(arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111") // v6K
|
|
||||||
INST(arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm") // v6
|
|
||||||
INST(arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm") // v6K
|
|
||||||
INST(arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm") // v6K
|
|
||||||
INST(arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm") // v6K
|
|
||||||
INST(arm_SWP, "SWP", "cccc00010000nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
INST(arm_SWP, "SWP", "cccc00010000nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
||||||
INST(arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
INST(arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
||||||
|
INST(arm_STL, "STL", "cccc00011000nnnn111111001001tttt") // v8
|
||||||
|
INST(arm_STLEX, "STLEX", "cccc00011000nnnndddd11101001tttt") // v8
|
||||||
|
INST(arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm") // v6
|
||||||
|
INST(arm_LDA, "LDA", "cccc00011001nnnndddd110010011111") // v8
|
||||||
|
INST(arm_LDAEX, "LDAEX", "cccc00011001nnnndddd111010011111") // v8
|
||||||
|
INST(arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111") // v6
|
||||||
|
INST(arm_STLEXD, "STLEXD", "cccc00011010nnnndddd11101001mmmm") // v8
|
||||||
|
INST(arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm") // v6K
|
||||||
|
INST(arm_LDAEXD, "LDAEXD", "cccc00011011nnnndddd111010011111") // v8
|
||||||
|
INST(arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111") // v6K
|
||||||
|
INST(arm_STLB, "STLB", "cccc00011100nnnn111111001001tttt") // v8
|
||||||
|
INST(arm_STLEXB, "STLEXB", "cccc00011100nnnndddd11101001mmmm") // v8
|
||||||
|
INST(arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm") // v6K
|
||||||
|
INST(arm_LDAB, "LDAB", "cccc00011101nnnndddd110010011111") // v8
|
||||||
|
INST(arm_LDAEXB, "LDAEXB", "cccc00011101nnnndddd111010011111") // v8
|
||||||
|
INST(arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111") // v6K
|
||||||
|
INST(arm_STLH, "STLH", "cccc00011110nnnn111111001001mmmm") // v8
|
||||||
|
INST(arm_STLEXH, "STLEXH", "cccc00011110nnnndddd11101001mmmm") // v8
|
||||||
|
INST(arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm") // v6K
|
||||||
|
INST(arm_LDAH, "LDAH", "cccc00011111nnnndddd110010011111") // v8
|
||||||
|
INST(arm_LDAEXH, "LDAEXH", "cccc00011111nnnndddd111010011111") // v8
|
||||||
|
INST(arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111") // v6K
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------")
|
INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------")
|
||||||
|
|
|
@ -1111,6 +1111,54 @@ public:
|
||||||
std::string arm_CLREX() {
|
std::string arm_CLREX() {
|
||||||
return "clrex";
|
return "clrex";
|
||||||
}
|
}
|
||||||
|
std::string arm_SWP(Cond cond, Reg n, Reg t, Reg t2) {
|
||||||
|
return fmt::format("swp{} {}, {}, [{}]", CondToString(cond), t, t2, n);
|
||||||
|
}
|
||||||
|
std::string arm_SWPB(Cond cond, Reg n, Reg t, Reg t2) {
|
||||||
|
return fmt::format("swpb{} {}, {}, [{}]", CondToString(cond), t, t2, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDA(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("lda{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDAB(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("ldab{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDAH(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("ldah{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDAEX(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("ldaex{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDAEXB(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("ldaexb{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDAEXD(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("ldaexd{} {}, {}, [{}]", CondToString(cond), t, t+1, n);
|
||||||
|
}
|
||||||
|
std::string arm_LDAEXH(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("ldaexh{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_STL(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("stl{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_STLB(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("stlb{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_STLH(Cond cond, Reg n, Reg t) {
|
||||||
|
return fmt::format("stlh{} {}, [{}]", CondToString(cond), t, n);
|
||||||
|
}
|
||||||
|
std::string arm_STLEX(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return fmt::format("stlex{} {}, {}, [{}]", CondToString(cond), d, m, n);
|
||||||
|
}
|
||||||
|
std::string arm_STLEXB(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return fmt::format("stlexb{} {}, {}, [{}]", CondToString(cond), d, m, n);
|
||||||
|
}
|
||||||
|
std::string arm_STLEXD(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return fmt::format("stlexd{} {}, {}, {}, [{}]", CondToString(cond), d, m, m+1, n);
|
||||||
|
}
|
||||||
|
std::string arm_STLEXH(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return fmt::format("stlexh{} {}, {}, [{}]", CondToString(cond), d, m, n);
|
||||||
|
}
|
||||||
std::string arm_LDREX(Cond cond, Reg n, Reg d) {
|
std::string arm_LDREX(Cond cond, Reg n, Reg d) {
|
||||||
return fmt::format("ldrex{} {}, [{}]", CondToString(cond), d, n);
|
return fmt::format("ldrex{} {}, [{}]", CondToString(cond), d, n);
|
||||||
}
|
}
|
||||||
|
@ -1135,12 +1183,6 @@ public:
|
||||||
std::string arm_STREXH(Cond cond, Reg n, Reg d, Reg m) {
|
std::string arm_STREXH(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return fmt::format("strexh{} {}, {}, [{}]", CondToString(cond), d, m, n);
|
return fmt::format("strexh{} {}, {}, [{}]", CondToString(cond), d, m, n);
|
||||||
}
|
}
|
||||||
std::string arm_SWP(Cond cond, Reg n, Reg t, Reg t2) {
|
|
||||||
return fmt::format("swp{} {}, {}, [{}]", CondToString(cond), t, t2, n);
|
|
||||||
}
|
|
||||||
std::string arm_SWPB(Cond cond, Reg n, Reg t, Reg t2) {
|
|
||||||
return fmt::format("swpb{} {}, {}, [{}]", CondToString(cond), t, t2, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status register access instructions
|
// Status register access instructions
|
||||||
std::string arm_CPS() { return "ice"; }
|
std::string arm_CPS() { return "ice"; }
|
||||||
|
|
|
@ -13,6 +13,284 @@ bool ArmTranslatorVisitor::arm_CLREX() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SWP<c> <Rt>, <Rt2>, [<Rn>]
|
||||||
|
// TODO: UNDEFINED if current mode is Hypervisor
|
||||||
|
bool ArmTranslatorVisitor::arm_SWP(Cond cond, Reg n, Reg t, Reg t2) {
|
||||||
|
if (t == Reg::PC || t2 == Reg::PC || n == Reg::PC || n == t || n == t2) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto data = ir.ReadMemory32(ir.GetRegister(n));
|
||||||
|
ir.WriteMemory32(ir.GetRegister(n), ir.GetRegister(t2));
|
||||||
|
// TODO: Alignment check
|
||||||
|
ir.SetRegister(t, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SWPB<c> <Rt>, <Rt2>, [<Rn>]
|
||||||
|
// TODO: UNDEFINED if current mode is Hypervisor
|
||||||
|
bool ArmTranslatorVisitor::arm_SWPB(Cond cond, Reg n, Reg t, Reg t2) {
|
||||||
|
if (t == Reg::PC || t2 == Reg::PC || n == Reg::PC || n == t || n == t2) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto data = ir.ReadMemory8(ir.GetRegister(n));
|
||||||
|
ir.WriteMemory8(ir.GetRegister(n), ir.LeastSignificantByte(ir.GetRegister(t2)));
|
||||||
|
// TODO: Alignment check
|
||||||
|
ir.SetRegister(t, ir.ZeroExtendByteToWord(data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LDA<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDA(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetRegister(t, ir.ReadMemory32(address)); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// LDAB<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDAB(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory8(address))); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// LDAH<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDAH(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory16(address))); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LDAEX<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDAEX(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetExclusive(address, 4);
|
||||||
|
ir.SetRegister(t, ir.ReadMemory32(address)); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LDAEXB<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDAEXB(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetExclusive(address, 1);
|
||||||
|
ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ReadMemory8(address))); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LDAEXD<c> <Rt>, <Rt2>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDAEXD(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::LR || t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetExclusive(address, 8);
|
||||||
|
|
||||||
|
// DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR
|
||||||
|
const auto lo = ir.ReadMemory32(address); // AccType::Ordered
|
||||||
|
ir.SetRegister(t, lo);
|
||||||
|
const auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4))); // AccType::Ordered
|
||||||
|
ir.SetRegister(t+1, hi);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LDAEXH<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_LDAEXH(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.SetExclusive(address, 2);
|
||||||
|
ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ReadMemory16(address))); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STL<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STL(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.WriteMemory32(address, ir.GetRegister(t)); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STLB<c> <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STLB(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STLH<c> <Rd>, <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STLH(Cond cond, Reg n, Reg t) {
|
||||||
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); // AccType::Ordered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STLEXB<c> <Rd>, <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STLEXB(Cond cond, Reg n, Reg d, Reg t) {
|
||||||
|
if (n == Reg::PC || d == Reg::PC || t == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == n || d == t) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
const auto value = ir.LeastSignificantByte(ir.GetRegister(t));
|
||||||
|
const auto passed = ir.ExclusiveWriteMemory8(address, value); // AccType::Ordered
|
||||||
|
ir.SetRegister(d, passed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// STLEXD<c> <Rd>, <Rt>, <Rt2>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STLEXD(Cond cond, Reg n, Reg d, Reg t) {
|
||||||
|
if (n == Reg::PC || d == Reg::PC || t == Reg::LR || static_cast<size_t>(t) % 2 == 1) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == n || d == t || d == t+1) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Reg t2 = t + 1;
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
const auto value_lo = ir.GetRegister(t);
|
||||||
|
const auto value_hi = ir.GetRegister(t2);
|
||||||
|
const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); // AccType::Ordered
|
||||||
|
ir.SetRegister(d, passed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STLEXH<c> <Rd>, <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STLEXH(Cond cond, Reg n, Reg d, Reg t) {
|
||||||
|
if (n == Reg::PC || d == Reg::PC || t == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == n || d == t) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
const auto value = ir.LeastSignificantHalf(ir.GetRegister(t));
|
||||||
|
const auto passed = ir.ExclusiveWriteMemory16(address, value); // AccType::Ordered
|
||||||
|
ir.SetRegister(d, passed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STLEX<c> <Rd>, <Rt>, [<Rn>]
|
||||||
|
bool ArmTranslatorVisitor::arm_STLEX(Cond cond, Reg n, Reg d, Reg t) {
|
||||||
|
if (n == Reg::PC || d == Reg::PC || t == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == n || d == t) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto address = ir.GetRegister(n);
|
||||||
|
const auto value = ir.GetRegister(t);
|
||||||
|
const auto passed = ir.ExclusiveWriteMemory32(address, value);
|
||||||
|
ir.SetRegister(d, passed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// LDREX<c> <Rt>, [<Rn>]
|
// LDREX<c> <Rt>, [<Rn>]
|
||||||
bool ArmTranslatorVisitor::arm_LDREX(Cond cond, Reg n, Reg t) {
|
bool ArmTranslatorVisitor::arm_LDREX(Cond cond, Reg n, Reg t) {
|
||||||
if (t == Reg::PC || n == Reg::PC) {
|
if (t == Reg::PC || n == Reg::PC) {
|
||||||
|
@ -168,41 +446,4 @@ bool ArmTranslatorVisitor::arm_STREXH(Cond cond, Reg n, Reg d, Reg t) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SWP<c> <Rt>, <Rt2>, [<Rn>]
|
|
||||||
// TODO: UNDEFINED if current mode is Hypervisor
|
|
||||||
bool ArmTranslatorVisitor::arm_SWP(Cond cond, Reg n, Reg t, Reg t2) {
|
|
||||||
if (t == Reg::PC || t2 == Reg::PC || n == Reg::PC || n == t || n == t2) {
|
|
||||||
return UnpredictableInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto data = ir.ReadMemory32(ir.GetRegister(n));
|
|
||||||
ir.WriteMemory32(ir.GetRegister(n), ir.GetRegister(t2));
|
|
||||||
// TODO: Alignment check
|
|
||||||
ir.SetRegister(t, data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SWPB<c> <Rt>, <Rt2>, [<Rn>]
|
|
||||||
// TODO: UNDEFINED if current mode is Hypervisor
|
|
||||||
bool ArmTranslatorVisitor::arm_SWPB(Cond cond, Reg n, Reg t, Reg t2) {
|
|
||||||
if (t == Reg::PC || t2 == Reg::PC || n == Reg::PC || n == t || n == t2) {
|
|
||||||
return UnpredictableInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto data = ir.ReadMemory8(ir.GetRegister(n));
|
|
||||||
ir.WriteMemory8(ir.GetRegister(n), ir.LeastSignificantByte(ir.GetRegister(t2)));
|
|
||||||
// TODO: Alignment check
|
|
||||||
ir.SetRegister(t, ir.ZeroExtendByteToWord(data));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -341,16 +341,30 @@ struct ArmTranslatorVisitor final {
|
||||||
|
|
||||||
// Synchronization Primitive instructions
|
// Synchronization Primitive instructions
|
||||||
bool arm_CLREX();
|
bool arm_CLREX();
|
||||||
bool arm_LDREX(Cond cond, Reg n, Reg t);
|
|
||||||
bool arm_LDREXB(Cond cond, Reg n, Reg t);
|
|
||||||
bool arm_LDREXD(Cond cond, Reg n, Reg t);
|
|
||||||
bool arm_LDREXH(Cond cond, Reg n, Reg t);
|
|
||||||
bool arm_STREX(Cond cond, Reg n, Reg d, Reg t);
|
|
||||||
bool arm_STREXB(Cond cond, Reg n, Reg d, Reg t);
|
|
||||||
bool arm_STREXD(Cond cond, Reg n, Reg d, Reg t);
|
|
||||||
bool arm_STREXH(Cond cond, Reg n, Reg d, Reg t);
|
|
||||||
bool arm_SWP(Cond cond, Reg n, Reg t, Reg t2);
|
bool arm_SWP(Cond cond, Reg n, Reg t, Reg t2);
|
||||||
bool arm_SWPB(Cond cond, Reg n, Reg t, Reg t2);
|
bool arm_SWPB(Cond cond, Reg n, Reg t, Reg t2);
|
||||||
|
bool arm_STL(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEX(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREX(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDA(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDAEX(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREX(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEXD(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREXD(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDAEXD(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREXD(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEXB(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREXB(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDAB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDAEXB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREXB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLH(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEXH(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREXH(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDAH(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDAEXH(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREXH(Cond cond, Reg n, Reg t);
|
||||||
|
|
||||||
// Status register access instructions
|
// Status register access instructions
|
||||||
bool arm_CPS();
|
bool arm_CPS();
|
||||||
|
|
|
@ -90,8 +90,8 @@ u32 GenRandomInst(u32 pc, bool is_last_inst) {
|
||||||
"arm_LDRBT", "arm_LDRBT", "arm_LDRHT", "arm_LDRHT", "arm_LDRSBT", "arm_LDRSBT", "arm_LDRSHT", "arm_LDRSHT", "arm_LDRT", "arm_LDRT",
|
"arm_LDRBT", "arm_LDRBT", "arm_LDRHT", "arm_LDRHT", "arm_LDRSBT", "arm_LDRSBT", "arm_LDRSHT", "arm_LDRSHT", "arm_LDRT", "arm_LDRT",
|
||||||
"arm_STRBT", "arm_STRBT", "arm_STRHT", "arm_STRHT", "arm_STRT", "arm_STRT",
|
"arm_STRBT", "arm_STRBT", "arm_STRHT", "arm_STRHT", "arm_STRT", "arm_STRT",
|
||||||
// Exclusive load/stores
|
// Exclusive load/stores
|
||||||
"arm_LDREXB", "arm_LDREXD", "arm_LDREXH", "arm_LDREX",
|
"arm_LDREXB", "arm_LDREXD", "arm_LDREXH", "arm_LDREX", "arm_LDAEXB", "arm_LDAEXD", "arm_LDAEXH", "arm_LDAEX",
|
||||||
"arm_STREXB", "arm_STREXD", "arm_STREXH", "arm_STREX",
|
"arm_STREXB", "arm_STREXD", "arm_STREXH", "arm_STREX", "arm_STLEXB", "arm_STLEXD", "arm_STLEXH", "arm_STLEX",
|
||||||
"arm_SWP", "arm_SWPB",
|
"arm_SWP", "arm_SWPB",
|
||||||
// Elevated load/store multiple instructions.
|
// Elevated load/store multiple instructions.
|
||||||
"arm_LDM_eret", "arm_LDM_usr",
|
"arm_LDM_eret", "arm_LDM_usr",
|
||||||
|
|
Loading…
Reference in a new issue