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:
parent
d8066b091b
commit
6241ff6be2
4 changed files with 75 additions and 4 deletions
|
@ -11,7 +11,7 @@ INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiii
|
||||||
//INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------")
|
//INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------")
|
||||||
|
|
||||||
// Load/Store Dual, Load/Store Exclusive, Table Branch
|
// 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_LDREX, "LDREX", "111010000101--------------------")
|
||||||
INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000U110nnnnttttssssiiiiiiii")
|
INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000U110nnnnttttssssiiiiiiii")
|
||||||
INST(thumb32_STRD_imm_2, "STRD (imm)", "11101001U1W0nnnnttttssssiiiiiiii")
|
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_lit_2, "LDRD (lit)", "11101001U1W11111ttttssssiiiiiiii")
|
||||||
INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000U111nnnnttttssssiiiiiiii")
|
INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000U111nnnnttttssssiiiiiiii")
|
||||||
INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001U1W1nnnnttttssssiiiiiiii")
|
INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001U1W1nnnnttttssssiiiiiiii")
|
||||||
//INST(thumb32_STREXB, "STREXB", "111010001100------------0100----")
|
INST(thumb32_STREXB, "STREXB", "111010001100nnnntttt11110100dddd")
|
||||||
//INST(thumb32_STREXH, "STREXH", "111010001100------------0101----")
|
INST(thumb32_STREXH, "STREXH", "111010001100nnnntttt11110101dddd")
|
||||||
//INST(thumb32_STREXD, "STREXD", "111010001100------------0111----")
|
INST(thumb32_STREXD, "STREXD", "111010001100nnnnttttuuuu0111dddd")
|
||||||
INST(thumb32_TBB, "TBB", "111010001101nnnn111100000000mmmm")
|
INST(thumb32_TBB, "TBB", "111010001101nnnn111100000000mmmm")
|
||||||
INST(thumb32_TBH, "TBH", "111010001101nnnn111100000001mmmm")
|
INST(thumb32_TBH, "TBH", "111010001101nnnn111100000001mmmm")
|
||||||
//INST(thumb32_LDREXB, "LDREXB", "111010001101------------0100----")
|
//INST(thumb32_LDREXB, "LDREXB", "111010001101------------0100----")
|
||||||
|
|
|
@ -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);
|
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) {
|
bool ThumbTranslatorVisitor::thumb32_TBB(Reg n, Reg m) {
|
||||||
return TableBranch(*this, n, m, false);
|
return TableBranch(*this, n, m, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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_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_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_TBB(Reg n, Reg m);
|
||||||
bool thumb32_TBH(Reg n, Reg m);
|
bool thumb32_TBH(Reg n, Reg m);
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,12 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
|
||||||
"thumb16_BKPT",
|
"thumb16_BKPT",
|
||||||
"thumb16_IT",
|
"thumb16_IT",
|
||||||
"thumb16_SETEND",
|
"thumb16_SETEND",
|
||||||
|
|
||||||
|
// Exclusive load/stores
|
||||||
|
"thumb32_STREX",
|
||||||
|
"thumb32_STREXB",
|
||||||
|
"thumb32_STREXD",
|
||||||
|
"thumb32_STREXH",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto& [fn, bitstring] : list) {
|
for (const auto& [fn, bitstring] : list) {
|
||||||
|
|
Loading…
Reference in a new issue