thumb32: Implement STREX variants

Implements the exclusive store instructions. Now all that remains for
ARMv7 load/stores to be done is the exclusive loads.
This commit is contained in:
Lioncash 2021-04-01 19:18:52 -04:00 committed by merry
parent d8066b091b
commit 6241ff6be2
4 changed files with 75 additions and 4 deletions

View file

@ -11,7 +11,7 @@ INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiii
//INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------")
// Load/Store Dual, Load/Store Exclusive, Table Branch
//INST(thumb32_STREX, "STREX", "111010000100--------------------")
INST(thumb32_STREX, "STREX", "111010000100nnnnttttddddiiiiiiii")
//INST(thumb32_LDREX, "LDREX", "111010000101--------------------")
INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000U110nnnnttttssssiiiiiiii")
INST(thumb32_STRD_imm_2, "STRD (imm)", "11101001U1W0nnnnttttssssiiiiiiii")
@ -19,9 +19,9 @@ INST(thumb32_LDRD_lit_1, "LDRD (lit)", "11101000U1111111ttttss
INST(thumb32_LDRD_lit_2, "LDRD (lit)", "11101001U1W11111ttttssssiiiiiiii")
INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000U111nnnnttttssssiiiiiiii")
INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001U1W1nnnnttttssssiiiiiiii")
//INST(thumb32_STREXB, "STREXB", "111010001100------------0100----")
//INST(thumb32_STREXH, "STREXH", "111010001100------------0101----")
//INST(thumb32_STREXD, "STREXD", "111010001100------------0111----")
INST(thumb32_STREXB, "STREXB", "111010001100nnnntttt11110100dddd")
INST(thumb32_STREXH, "STREXH", "111010001100nnnntttt11110101dddd")
INST(thumb32_STREXD, "STREXD", "111010001100nnnnttttuuuu0111dddd")
INST(thumb32_TBB, "TBB", "111010001101nnnn111100000000mmmm")
INST(thumb32_TBH, "TBH", "111010001101nnnn111100000001mmmm")
//INST(thumb32_LDREXB, "LDREXB", "111010001101------------0100----")

View file

@ -135,6 +135,67 @@ bool ThumbTranslatorVisitor::thumb32_STRD_imm_2(bool U, bool W, Reg n, Reg t, Re
return StoreDual(*this, true, U, W, n, t, t2, imm8);
}
bool ThumbTranslatorVisitor::thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8) {
if (d == Reg::PC || t == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction();
}
if (d == n || d == t) {
return UnpredictableInstruction();
}
const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm8.ZeroExtend()));
const auto value = ir.GetRegister(t);
const auto passed = ir.ExclusiveWriteMemory32(address, value);
ir.SetRegister(d, passed);
return true;
}
bool ThumbTranslatorVisitor::thumb32_STREXB(Reg n, Reg t, Reg d) {
if (d == Reg::PC || t == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction();
}
if (d == n || d == t) {
return UnpredictableInstruction();
}
const auto address = ir.GetRegister(n);
const auto value = ir.LeastSignificantByte(ir.GetRegister(t));
const auto passed = ir.ExclusiveWriteMemory8(address, value);
ir.SetRegister(d, passed);
return true;
}
bool ThumbTranslatorVisitor::thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d) {
if (d == Reg::PC || t == Reg::PC || t2 == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction();
}
if (d == n || d == t || d == t2) {
return UnpredictableInstruction();
}
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);
ir.SetRegister(d, passed);
return true;
}
bool ThumbTranslatorVisitor::thumb32_STREXH(Reg n, Reg t, Reg d) {
if (d == Reg::PC || t == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction();
}
if (d == n || d == t) {
return UnpredictableInstruction();
}
const auto address = ir.GetRegister(n);
const auto value = ir.LeastSignificantHalf(ir.GetRegister(t));
const auto passed = ir.ExclusiveWriteMemory16(address, value);
ir.SetRegister(d, passed);
return true;
}
bool ThumbTranslatorVisitor::thumb32_TBB(Reg n, Reg m) {
return TableBranch(*this, n, m, false);
}

View file

@ -186,6 +186,10 @@ struct ThumbTranslatorVisitor final {
bool thumb32_LDRD_lit_2(bool U, bool W, Reg t, Reg t2, Imm<8> imm8);
bool thumb32_STRD_imm_1(bool U, Reg n, Reg t, Reg t2, Imm<8> imm8);
bool thumb32_STRD_imm_2(bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8);
bool thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8);
bool thumb32_STREXB(Reg n, Reg t, Reg d);
bool thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d);
bool thumb32_STREXH(Reg n, Reg t, Reg d);
bool thumb32_TBB(Reg n, Reg m);
bool thumb32_TBH(Reg n, Reg m);

View file

@ -166,6 +166,12 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
"thumb16_BKPT",
"thumb16_IT",
"thumb16_SETEND",
// Exclusive load/stores
"thumb32_STREX",
"thumb32_STREXB",
"thumb32_STREXD",
"thumb32_STREXH",
};
for (const auto& [fn, bitstring] : list) {