diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index c4008486..9c26ebc4 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -15,8 +15,8 @@ INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiii //INST(thumb32_LDREX, "LDREX", "111010000101--------------------") INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000U110nnnnttttssssiiiiiiii") INST(thumb32_STRD_imm_2, "STRD (imm)", "11101001U1W0nnnnttttssssiiiiiiii") -//INST(thumb32_LDRD_imm_1, "LDRD (lit)", "11101000-1111111----------------") -//INST(thumb32_LDRD_imm_2, "LDRD (lit)", "11101001-1-11111----------------") +INST(thumb32_LDRD_lit_1, "LDRD (lit)", "11101000U1111111ttttssssiiiiiiii") +INST(thumb32_LDRD_lit_2, "LDRD (lit)", "11101001U1W11111ttttssssiiiiiiii") //INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000-111--------------------") //INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001-1-1--------------------") //INST(thumb32_STREXB, "STREXB", "111010001100------------0100----") diff --git a/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp index 86eeda5d..9065f0bc 100644 --- a/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp +++ b/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -39,6 +39,24 @@ static bool TableBranch(ThumbTranslatorVisitor& v, Reg n, Reg m, bool half) { return false; } +static bool LoadDualLiteral(ThumbTranslatorVisitor& v, bool U, bool W, Reg t, Reg t2, Imm<8> imm8) { + if (t == Reg::PC || t2 == Reg::PC || t == t2) { + return v.UnpredictableInstruction(); + } + if (W) { + return v.UnpredictableInstruction(); + } + + const auto imm = imm8.ZeroExtend() << 2; + const auto address_1 = U ? v.ir.Add(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)) + : v.ir.Sub(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)); + const auto address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + + v.ir.SetRegister(t, v.ir.ReadMemory32(address_1)); + v.ir.SetRegister(t2, v.ir.ReadMemory32(address_2)); + return true; +} + static bool StoreDual(ThumbTranslatorVisitor& v, bool P, bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8) { if (W && (n == t || n == t2)) { return v.UnpredictableInstruction(); @@ -67,6 +85,14 @@ static bool StoreDual(ThumbTranslatorVisitor& v, bool P, bool U, bool W, Reg n, return true; } +bool ThumbTranslatorVisitor::thumb32_LDRD_lit_1(bool U, Reg t, Reg t2, Imm<8> imm8) { + return LoadDualLiteral(*this, U, true, t, t2, imm8); +} + +bool ThumbTranslatorVisitor::thumb32_LDRD_lit_2(bool U, bool W, Reg t, Reg t2, Imm<8> imm8) { + return LoadDualLiteral(*this, U, W, t, t2, imm8); +} + bool ThumbTranslatorVisitor::thumb32_STRD_imm_1(bool U, Reg n, Reg t, Reg t2, Imm<8> imm8) { return StoreDual(*this, false, U, true, n, t, t2, imm8); } diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index d456a19a..035cd444 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -180,6 +180,8 @@ struct ThumbTranslatorVisitor final { bool thumb32_STMDB(bool W, Reg n, Imm<15> reg_list); // thumb32 load/store dual, load/store exclusive, table branch instructions + bool thumb32_LDRD_lit_1(bool U, 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_2(bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8); bool thumb32_TBB(Reg n, Reg m);