From 77761ba0328affc100b71233489cdda2b9934364 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 14:01:18 -0500
Subject: [PATCH 1/7] Added the format strings for LDRT encodings A1 and A2.

---
 src/frontend/decoder/arm.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h
index a02339a4..fb2f6c26 100644
--- a/src/frontend/decoder/arm.h
+++ b/src/frontend/decoder/arm.h
@@ -197,8 +197,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
         //INST(&V::arm_LDRSH_reg,   "LDRSH (reg)",         "cccc000pu0w1nnnndddd00001111mmmm"),
         //INST(&V::arm_LDRSHT,      "LDRSHT (A1)",         "----0000-111------------1111----"),
         //INST(&V::arm_LDRSHT,      "LDRSHT (A2)",         "----0000-011--------00001111----"),
-        //INST(&V::arm_LDRT,        "LDRT (A1)",           "----0100-011--------------------"),
-        //INST(&V::arm_LDRT,        "LDRT (A2)",           "----0110-011---------------0----"),
+        //INST(&V::arm_LDRT,        "LDRT (A1)",           "cccc0100u011nnnnttttvvvvvvvvvvvv"),
+        //INST(&V::arm_LDRT,        "LDRT (A2)",           "cccc0110u011nnnnttttvvvvvrr0mmmm"),
         //INST(&V::arm_STR_imm,     "STR (imm)",           "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
         //INST(&V::arm_STR_reg,     "STR (reg)",           "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
         //INST(&V::arm_STRB_imm,    "STRB (imm)",          "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),

From 5d5ea9325cccc1a21ff9da58e76e8696cbe488a7 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 14:05:53 -0500
Subject: [PATCH 2/7] Added format strings for ARM STRT encodings A1 and A2

---
 src/frontend/decoder/arm.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h
index fb2f6c26..a54541d4 100644
--- a/src/frontend/decoder/arm.h
+++ b/src/frontend/decoder/arm.h
@@ -211,8 +211,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
         //INST(&V::arm_STRH_reg,    "STRH (reg)",          "cccc000pu0w0nnnndddd00001011mmmm"),
         //INST(&V::arm_STRHT,       "STRHT (A1)",          "----0000-110------------1011----"),
         //INST(&V::arm_STRHT,       "STRHT (A2)",          "----0000-010--------00001011----"),
-        //INST(&V::arm_STRT,        "STRT (A1)",           "----0100-010--------------------"),
-        //INST(&V::arm_STRT,        "STRT (A2)",           "----0110-010---------------0----"),
+        //INST(&V::arm_STRT,        "STRT (A1)",           "cccc0100u010nnnnttttvvvvvvvvvvvv"),
+        //INST(&V::arm_STRT,        "STRT (A2)",           "cccc0110u010nnnnttttvvvvvrr0mmmm"),
 
         // Load/Store Multiple instructions
         //INST(&V::arm_LDM,         "LDM",                 "cccc100pu0w1nnnnxxxxxxxxxxxxxxxx"), // all

From 8617bf80a19a161680c4c7ce0248688fba7e8c50 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 14:18:39 -0500
Subject: [PATCH 3/7] Added format strings for ARM LDRBT encodings A1 and A2

---
 src/frontend/decoder/arm.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h
index a54541d4..070a6521 100644
--- a/src/frontend/decoder/arm.h
+++ b/src/frontend/decoder/arm.h
@@ -181,8 +181,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
         //INST(&V::arm_LDR_reg,     "LDR (reg)",           "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
         //INST(&V::arm_LDRB_imm,    "LDRB (imm)",          "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
         //INST(&V::arm_LDRB_reg,    "LDRB (reg)",          "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
-        //INST(&V::arm_LDRBT,       "LDRBT (A1)",          "----0100-111--------------------"),
-        //INST(&V::arm_LDRBT,       "LDRBT (A2)",          "----0110-111---------------0----"),
+        //INST(&V::arm_LDRBT,       "LDRBT (A1)",          "cccc0100u111nnnnttttvvvvvvvvvvvv"),
+        //INST(&V::arm_LDRBT,       "LDRBT (A2)",          "cccc0110u111nnnnttttvvvvvrr0mmmm"),
         //INST(&V::arm_LDRD_imm,    "LDRD (imm)",          "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
         //INST(&V::arm_LDRD_reg,    "LDRD (reg)",          "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
         //INST(&V::arm_LDRH_imm,    "LDRH (imm)",          "cccc000pu1w1nnnnddddvvvv1011vvvv"),

From ccc61472b956c33317cf48c5982f9fb187537d0d Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 14:20:58 -0500
Subject: [PATCH 4/7] Added format strings for ARM STRBT encodings A1 and A2

---
 src/frontend/decoder/arm.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h
index 070a6521..d7ffd709 100644
--- a/src/frontend/decoder/arm.h
+++ b/src/frontend/decoder/arm.h
@@ -203,8 +203,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
         //INST(&V::arm_STR_reg,     "STR (reg)",           "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
         //INST(&V::arm_STRB_imm,    "STRB (imm)",          "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
         //INST(&V::arm_STRB_reg,    "STRB (reg)",          "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
-        //INST(&V::arm_STRBT,       "STRBT (A1)",          "----0100-110--------------------"),
-        //INST(&V::arm_STRBT,       "STRBT (A2)",          "----0110-110---------------0----"),
+        //INST(&V::arm_STRBT,       "STRBT (A1)",          "cccc0100u110nnnnttttvvvvvvvvvvvv"),
+        //INST(&V::arm_STRBT,       "STRBT (A2)",          "cccc0110u110nnnnttttvvvvvrr0mmmm"),
         //INST(&V::arm_STRD_imm,    "STRD (imm)",          "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
         //INST(&V::arm_STRD_reg,    "STRD (reg)",          "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
         //INST(&V::arm_STRH_imm,    "STRH (imm)",          "cccc000pu1w0nnnnddddvvvv1011vvvv"),

From c330d9e0e30253ebf42eecfbdedc3c67f3d82caa Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 16:10:35 -0500
Subject: [PATCH 5/7] Increase the chance of generating instructions without
 conditions in the REV/REVSH/REV16 tests.

---
 tests/arm/fuzz_arm.cpp | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp
index d2834eb6..ae19305e 100644
--- a/tests/arm/fuzz_arm.cpp
+++ b/tests/arm/fuzz_arm.cpp
@@ -366,29 +366,44 @@ TEST_CASE("Fuzz ARM reversal instructions", "[JitX64]") {
         return Dynarmic::Common::Bits<0, 3>(instr) != 0b1111 && Dynarmic::Common::Bits<12, 15>(instr) != 0b1111;
     };
 
-    const std::array<InstructionGenerator, 3> reg_instructions = {
+    const std::array<InstructionGenerator, 3> rev_instructions = {
         {
-            InstructionGenerator("cccc011010111111dddd11110011mmmm", is_valid),
-            InstructionGenerator("cccc011010111111dddd11111011mmmm", is_valid),
-            InstructionGenerator("cccc011011111111dddd11111011mmmm", is_valid),
+            InstructionGenerator("0000011010111111dddd11110011mmmm", is_valid),
+            InstructionGenerator("0000011010111111dddd11111011mmmm", is_valid),
+            InstructionGenerator("0000011011111111dddd11111011mmmm", is_valid),
         }
     };
 
     SECTION("REV tests") {
-        FuzzJitArm(1, 1, 10000, [&reg_instructions]() -> u32 {
-            return reg_instructions[0].Generate();
+        FuzzJitArm(1, 1, 10000, [&rev_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+            return rev_instructions[0].Generate() | (cond << 28);
         });
     }
 
     SECTION("REV16 tests") {
-        FuzzJitArm(1, 1, 10000, [&reg_instructions]() -> u32 {
-            return reg_instructions[1].Generate();
+        FuzzJitArm(1, 1, 10000, [&rev_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+            return rev_instructions[1].Generate() | (cond << 28);
         });
     }
 
     SECTION("REVSH tests") {
-        FuzzJitArm(1, 1, 10000, [&reg_instructions]() -> u32 {
-            return reg_instructions[2].Generate();
+        FuzzJitArm(1, 1, 10000, [&rev_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+            return rev_instructions[2].Generate() | (cond << 28);
         });
     }
 }

From 426ffc997182ae53aacef23fafbf40bf69cdec54 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 16:13:02 -0500
Subject: [PATCH 6/7] Added ARM fuzz tests for LDRD/LDR/LDRT/LDRB/LDRBT/LDRH
 and STRD/STR/STRT/STRB/STRBT/STRH.

These tests do not test the behavior of writing to the PC.
---
 tests/arm/fuzz_arm.cpp | 151 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)

diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp
index ae19305e..230dd716 100644
--- a/tests/arm/fuzz_arm.cpp
+++ b/tests/arm/fuzz_arm.cpp
@@ -407,3 +407,154 @@ TEST_CASE("Fuzz ARM reversal instructions", "[JitX64]") {
         });
     }
 }
+
+TEST_CASE("Fuzz ARM Load/Store instructions", "[JitX64]") {
+    auto forbid_r15 = [](u32 inst) -> bool {
+        return Dynarmic::Common::Bits<12, 15>(inst) != 0b1111;
+    };
+
+    auto forbid_r14_and_r15 = [](u32 inst) -> bool {
+        return Dynarmic::Common::Bits<13, 15>(inst) != 0b111;
+    };
+
+    const std::array<InstructionGenerator, 4> doubleword_instructions = {
+        {
+            // Load
+            InstructionGenerator("0000000pu1w0nnnnddd0vvvv1101vvvv", forbid_r14_and_r15),
+            InstructionGenerator("0000000pu0w0nnnnddd000001101mmmm", forbid_r14_and_r15),
+
+            // Store
+            InstructionGenerator("0000000pu1w0nnnnddd0vvvv1111vvvv", forbid_r14_and_r15),
+            InstructionGenerator("0000000pu0w0nnnnddd000001111mmmm", forbid_r14_and_r15),
+        }
+    };
+
+    const std::array<InstructionGenerator, 8> word_instructions = {
+        {
+            // Load
+            InstructionGenerator("0000010pu0w1nnnnddddvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("0000011pu0w1nnnnddddvvvvvrr0mmmm", forbid_r15),
+            InstructionGenerator("00000100u011nnnnttttmmmmmmmmmmmm", forbid_r15),
+            InstructionGenerator("00000110u011nnnnttttvvvvvrr0mmmm", forbid_r15),
+
+            // Store
+            InstructionGenerator("0000010pu0w0nnnnddddvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("0000011pu0w0nnnnddddvvvvvrr0mmmm", forbid_r15),
+            InstructionGenerator("00000100u010nnnnttttvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("00000110u010nnnnttttvvvvvrr0mmmm", forbid_r15),
+        }
+    };
+
+    const std::array<InstructionGenerator, 6> halfword_instructions = {
+        {
+            // Load
+            InstructionGenerator("0000000pu1w1nnnnddddvvvv1011vvvv", forbid_r15),
+            InstructionGenerator("0000000pu0w1nnnndddd00001011mmmm", forbid_r15),
+            // InstructionGenerator("----0000-111------------1011----"), // LDRHT (A1) Not available in ARMv6K
+            // InstructionGenerator("----0000-011--------00001011----"), // LDRHT (A2) Not available in ARMv6K
+            InstructionGenerator("0000000pu1w1nnnnddddvvvv1111vvvv", forbid_r15),
+            InstructionGenerator("0000000pu0w1nnnndddd00001111mmmm", forbid_r15),
+            // InstructionGenerator("----0000-111------------1111----"), // LDRSHT (A1) Not available in ARMv6K
+            // InstructionGenerator("----0000-011--------00001111----"), // LDRSHT (A2) Not available in ARMv6K
+
+
+            // Store
+            InstructionGenerator("0000000pu1w0nnnnddddvvvv1011vvvv", forbid_r15),
+            InstructionGenerator("0000000pu0w0nnnndddd00001011mmmm", forbid_r15),
+            // InstructionGenerator("----0000-110------------1011----"), // STRHT (A1) Not available in ARMv6K
+            // InstructionGenerator("----0000-010--------00001011----"), // STRHT (A2) Not available in ARMv6K
+        }
+    };
+
+    const std::array<InstructionGenerator, 10> byte_instructions = {
+        {
+            // Load
+            InstructionGenerator("0000010pu1w1nnnnddddvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("0000011pu1w1nnnnddddvvvvvrr0mmmm", forbid_r15),
+            InstructionGenerator("00000100u111nnnnttttvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("00000110u111nnnnttttvvvvvrr0mmmm", forbid_r15),
+            InstructionGenerator("0000000pu1w1nnnnddddvvvv1101vvvv", forbid_r15),
+            InstructionGenerator("0000000pu0w1nnnndddd00001101mmmm", forbid_r15),
+            // InstructionGenerator("----0000-111------------1101----"), // LDRSBT (A1) Not available in ARMv6K
+            // InstructionGenerator("----0000-011--------00001101----"), // LDRSBT (A2) Not available in ARMv6K
+
+
+            // Store
+            InstructionGenerator("0000010pu1w0nnnnddddvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("0000011pu1w0nnnnddddvvvvvrr0mmmm", forbid_r15),
+            InstructionGenerator("00000100u110nnnnttttvvvvvvvvvvvv", forbid_r15),
+            InstructionGenerator("00000110u110nnnnttttvvvvvrr0mmmm", forbid_r15),
+        }
+    };
+
+    SECTION("Doubleword tests") {
+        FuzzJitArm(1, 1, 10000, [&doubleword_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+
+            return doubleword_instructions[RandInt<size_t>(0, doubleword_instructions.size() - 1)].Generate() | (cond << 28);
+        });
+    }
+
+    SECTION("Word tests") {
+        FuzzJitArm(1, 1, 10000, [&word_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+            return word_instructions[RandInt<size_t>(0, word_instructions.size() - 1)].Generate() | (cond << 28);
+        });
+    }
+
+    SECTION("Halfword tests") {
+        FuzzJitArm(1, 1, 10000, [&halfword_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+            return halfword_instructions[RandInt<size_t>(0, halfword_instructions.size() - 1)].Generate() | (cond << 28);
+        });
+    }
+
+    SECTION("Byte tests") {
+        FuzzJitArm(1, 1, 10000, [&byte_instructions]() -> u32 {
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+            return byte_instructions[RandInt<size_t>(0, byte_instructions.size() - 1)].Generate() | (cond << 28);
+        });
+    }
+
+    SECTION("Mixed tests") {
+        FuzzJitArm(10, 10, 10000, [&]() -> u32 {
+            size_t selection = RandInt<size_t>(0, 3);
+
+            u32 cond = 0xE;
+            // Have a one-in-twenty-five chance of actually having a cond.
+            if (RandInt(1, 25) == 1) {
+                cond = RandInt<u32>(0x0, 0xD);
+            }
+
+            switch (selection) {
+            case 0:
+                return doubleword_instructions[RandInt<size_t>(0, doubleword_instructions.size() - 1)].Generate() | (cond << 28);
+            case 1:
+                return word_instructions[RandInt<size_t>(0, word_instructions.size() - 1)].Generate() | (cond << 28);
+            case 2:
+                return halfword_instructions[RandInt<size_t>(0, halfword_instructions.size() - 1)].Generate() | (cond << 28);
+            case 3:
+                return byte_instructions[RandInt<size_t>(0, byte_instructions.size() - 1)].Generate() | (cond << 28);
+            }
+
+            return 0;
+        });
+    }
+
+}
\ No newline at end of file

From fce8f75077d40a2028185bf4685bd40eed4d50f0 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 18 Jul 2016 16:13:33 -0500
Subject: [PATCH 7/7] Added a dummy (always fail) ARM test about Load/Store
 instructions that write to the PC.

---
 tests/arm/fuzz_arm.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp
index 230dd716..a520448f 100644
--- a/tests/arm/fuzz_arm.cpp
+++ b/tests/arm/fuzz_arm.cpp
@@ -557,4 +557,8 @@ TEST_CASE("Fuzz ARM Load/Store instructions", "[JitX64]") {
         });
     }
 
+    SECTION("Write to PC") {
+        // TODO
+        FAIL();
+    }
 }
\ No newline at end of file