From f9755870bbbfef9203d4bb9cd090a0b8b22f13e1 Mon Sep 17 00:00:00 2001
From: MerryMage <MerryMage@users.noreply.github.com>
Date: Mon, 18 Jul 2016 18:01:15 +0100
Subject: [PATCH] Implement Thumb Instructions: LDR (reg), LDRH (reg), LDRSH
 (reg), LDRB (reg), LDRSB (reg)

---
 src/frontend/decoder/thumb16.h                | 14 +++---
 .../disassembler/disassembler_thumb.cpp       | 20 +++++++++
 src/frontend/translate/translate_thumb.cpp    | 45 +++++++++++++++++++
 3 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/src/frontend/decoder/thumb16.h b/src/frontend/decoder/thumb16.h
index 9bc9d065..18d2d369 100644
--- a/src/frontend/decoder/thumb16.h
+++ b/src/frontend/decoder/thumb16.h
@@ -102,14 +102,14 @@ boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
         INST(&V::thumb16_STR_reg,        "STR (reg)",                "0101000mmmnnnttt"),
         INST(&V::thumb16_STRH_reg,       "STRH (reg)",               "0101001mmmnnnttt"),
         INST(&V::thumb16_STRB_reg,       "STRB (reg)",               "0101010mmmnnnttt"),
-        //INST(&V::thumb16_LDRSB_rrr,      "LDRSB (rrr)",              "0101011mmmnnnddd"),
-        //INST(&V::thumb16_LDR_rrr,        "LDR (rrr)",                "0101100mmmnnnddd"),
-        //INST(&V::thumb16_LDRH_rrr,       "LDRH (rrr)",               "0101101mmmnnnddd"),
-        //INST(&V::thumb16_LDRB_rrr,       "LDRB (rrr)",               "0101110mmmnnnddd"),
-        //INST(&V::thumb16_LDRSH_rrr,      "LDRSH (rrr)",              "0101111mmmnnnddd"),
+        INST(&V::thumb16_LDRSB_reg,      "LDRSB (reg)",              "0101011mmmnnnttt"),
+        INST(&V::thumb16_LDR_reg,        "LDR (reg)",                "0101100mmmnnnttt"),
+        INST(&V::thumb16_LDRH_reg,       "LDRH (reg)",               "0101101mmmnnnttt"),
+        INST(&V::thumb16_LDRB_reg,       "LDRB (reg)",               "0101110mmmnnnttt"),
+        INST(&V::thumb16_LDRSH_reg,      "LDRSH (reg)",              "0101111mmmnnnttt"),
         INST(&V::thumb16_LDR_imm_t1,     "LDR (imm, T1)",            "01101vvvvvnnnttt"),
-        //INST(&V::thumb16_STRH_rri,       "STRH (rri)",               "10000vvvvvnnnddd"),
-        //INST(&V::thumb16_LDRH_rri,       "LDRH (rri)",               "10001vvvvvnnnddd"),
+        //INST(&V::thumb16_STRH_imm,       "STRH (imm)",               "10000vvvvvnnnttt"),
+        //INST(&V::thumb16_LDRH_imm,       "LDRH (imm)",               "10001vvvvvnnnttt"),
         //INST(&V::thumb16_STR_sp,         "STR (SP)",                 "10010dddvvvvvvvv"),
         //INST(&V::thumb16_LDR_sp,         "LDR (SP)",                 "10011dddvvvvvvvv"),
 
diff --git a/src/frontend/disassembler/disassembler_thumb.cpp b/src/frontend/disassembler/disassembler_thumb.cpp
index 235ce780..6881704e 100644
--- a/src/frontend/disassembler/disassembler_thumb.cpp
+++ b/src/frontend/disassembler/disassembler_thumb.cpp
@@ -239,6 +239,26 @@ public:
         return Common::StringFromFormat("strb %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
     }
 
+    std::string thumb16_LDRSB_reg(Reg m, Reg n, Reg t) {
+        return Common::StringFromFormat("ldrsb %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
+    }
+
+    std::string thumb16_LDR_reg(Reg m, Reg n, Reg t) {
+        return Common::StringFromFormat("ldr %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
+    }
+
+    std::string thumb16_LDRH_reg(Reg m, Reg n, Reg t) {
+        return Common::StringFromFormat("ldrh %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
+    }
+
+    std::string thumb16_LDRB_reg(Reg m, Reg n, Reg t) {
+        return Common::StringFromFormat("ldrb %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
+    }
+
+    std::string thumb16_LDRSH_reg(Reg m, Reg n, Reg t) {
+        return Common::StringFromFormat("ldrsh %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
+    }
+
     std::string thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
         u32 imm32 = imm5 << 2;
         return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
diff --git a/src/frontend/translate/translate_thumb.cpp b/src/frontend/translate/translate_thumb.cpp
index 98bb5fd4..cac60d15 100644
--- a/src/frontend/translate/translate_thumb.cpp
+++ b/src/frontend/translate/translate_thumb.cpp
@@ -431,6 +431,51 @@ struct ThumbTranslatorVisitor final {
         return true;
     }
 
+    bool thumb16_LDRSB_reg(Reg m, Reg n, Reg t) {
+        // LDRSB <Rt>, [<Rn>, <Rm>]
+        // Rt cannot encode R15.
+        auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
+        auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address));
+        ir.SetRegister(t, data);
+        return true;
+    }
+
+    bool thumb16_LDR_reg(Reg m, Reg n, Reg t) {
+        // LDR <Rt>, [<Rn>, <Rm>]
+        // Rt cannot encode R15.
+        auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
+        auto data = ir.ReadMemory32(address);
+        ir.SetRegister(t, data);
+        return true;
+    }
+
+    bool thumb16_LDRH_reg(Reg m, Reg n, Reg t) {
+        // LDRH <Rt>, [<Rn>, <Rm>]
+        // Rt cannot encode R15.
+        auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
+        auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address));
+        ir.SetRegister(t, data);
+        return true;
+    }
+
+    bool thumb16_LDRB_reg(Reg m, Reg n, Reg t) {
+        // LDRB <Rt>, [<Rn>, <Rm>]
+        // Rt cannot encode R15.
+        auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
+        auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address));
+        ir.SetRegister(t, data);
+        return true;
+    }
+
+    bool thumb16_LDRSH_reg(Reg m, Reg n, Reg t) {
+        // LDRH <Rt>, [<Rn>, <Rm>]
+        // Rt cannot encode R15.
+        auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
+        auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address));
+        ir.SetRegister(t, data);
+        return true;
+    }
+
     bool thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
         u32 imm32 = imm5 << 2;
         // LDR <Rt>, [<Rn>, #<imm>}