From 1b524ce0e645e451ca76723f4f86fe2a71c1adf2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 25 May 2016 23:19:42 +0200
Subject: Fixed various mistakes in the decoding of ARM instructions.

---
 ChangeLog                                 |   7 ++
 src/arch/arm/v7/arm.c                     | 144 ++++++++++--------------------
 src/arch/arm/v7/opcodes/opcodes_tmp_arm.h |   2 -
 src/arch/arm/v7/pseudo.c                  |   6 +-
 4 files changed, 58 insertions(+), 101 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6895d32..3660bbd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+16-05-25  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/arm/v7/arm.c:
+	* src/arch/arm/v7/opcodes/opcodes_tmp_arm.h:
+	* src/arch/arm/v7/pseudo.c:
+	Fix various mistakes in the decoding of ARM instructions.
+
 16-05-24  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/area.c:
diff --git a/src/arch/arm/v7/arm.c b/src/arch/arm/v7/arm.c
index af92096..9a29939 100644
--- a/src/arch/arm/v7/arm.c
+++ b/src/arch/arm/v7/arm.c
@@ -531,7 +531,7 @@ static GArchInstruction *process_armv7_arm_data_processing_immediate(uint32_t ra
      * § A5.2.3 Data-processing (immediate)
      */
 
-    if ((raw & 0x0e000000) != 0x04000000) return NULL;
+    if ((raw & 0x0e000000) != 0x02000000) return NULL;
 
     result = NULL;
 
@@ -1101,7 +1101,7 @@ static GArchInstruction *process_armv7_arm_miscellaneous_instructions(uint32_t r
      * § A5.2.12 Miscellaneous instructions
      */
 
-    if ((raw & 0x0f900080) != 0x00100000) return NULL;
+    if ((raw & 0x0f900080) != 0x01000000) return NULL;
 
     result = NULL;
 
@@ -1229,126 +1229,74 @@ static GArchInstruction *process_armv7_arm_load_store_word_and_unsigned_byte(uin
     rn = (raw >> 16) & 0xf;
     b = (raw >> 4) & 0x1;
 
-    if ((op1 & b10111) == b00010)
+    if (a == b0)
     {
-        if (a == b0)
-        {
-            result = armv7_read_arm_instr_strt(raw);
-            goto a53_done;
-        }
-        else if (/*a == b1 && */b == b0)
-            goto a53_done;
-    }
-    else if ((op1 & b00101) == b00000)
-    {
-        if (a == b0)
-        {
+        if ((op1 & b00101) == b00000 && (op1 & b10111) != b00010)
             result = armv7_read_arm_instr_str_immediate_arm(raw);
-            goto a53_done;
-        }
-        else if (/*a == b1 && */b == b0)
-        {
-            result = armv7_read_arm_instr_str_register(raw);
-            goto a53_done;
-        }
-    }
 
-    if ((op1 & b10111) == b00011)
-    {
-        if (a == b0)
-        {
-            result = armv7_read_arm_instr_ldrt(raw);
-            goto a53_done;
-        }
-        else if (/*a == b1 && */b == b0)
-            goto a53_done;
-    }
-    else if ((op1 & b00101) == b00001)
-    {
-        if (a == b0)
+        else if ((op1 & b10111) == b00010)
+            result = armv7_read_arm_instr_strt(raw);
+
+        else if ((op1 & b00101) == b00001 && (op1 & b10111) != b00011)
         {
-            if (rn == b1111)
-                result = armv7_read_arm_instr_ldr_literal(raw);
-            else
+            if (rn != b1111)
                 result = armv7_read_arm_instr_ldr_immediate_arm(raw);
+            else
+                result = armv7_read_arm_instr_ldr_literal(raw);
+        }
 
-            goto a53_done;
+        else if ((op1 & b10111) == b00011)
+            result = armv7_read_arm_instr_ldrt(raw);
 
-        }
-        else if (/*a == b1 && */b == b0)
-        {
-            result = armv7_read_arm_instr_ldr_register(raw);
-            goto a53_done;
-        }
-    }
+        else if ((op1 & b00101) == b00100 && (op1 & b10110) != b00110)
+            result = armv7_read_arm_instr_strb_immediate_arm(raw);
 
-    if ((op1 & b10111) == b00110)
-    {
-        if (a == b0)
-        {
+        else if ((op1 & b10110) == b00110)
             result = armv7_read_arm_instr_strbt(raw);
-            goto a53_done;
-        }
-        else if (/*a == b1 && */b == b0)
-            goto a53_done;
-    }
-    else if ((op1 & b00101) == b00100)
-    {
-        if (a == b0)
-        {
-            result = armv7_read_arm_instr_strb_immediate_arm(raw);
-            goto a53_done;
-        }
-        else if (/*a == b1 && */b == b0)
-        {
-            result = armv7_read_arm_instr_strb_register(raw);
-            goto a53_done;
-        }
-    }
 
-    if ((op1 & b10111) == b00111)
-    {
-        if (a == b0)
+        else if ((op1 & b00101) == b00101 && (op1 & b10111) != b00111)
         {
-            result = armv7_read_arm_instr_ldrbt(raw);
-            goto a53_done;
-        }
-        else if (/*a == b1 && */b == b0)
-            goto a53_done;
-    }
-    else if ((op1 & b00101) == b00101)
-    {
-        if (a == b0)
-        {
-            if (rn == b1111)
-                result = armv7_read_arm_instr_ldrb_literal(raw);
-            else
+            if (rn != b1111)
                 result = armv7_read_arm_instr_ldrb_immediate_arm(raw);
-
-            goto a53_done;
-
-        }
-        else if (/*a == b1 && */b == b0)
-        {
-            result = armv7_read_arm_instr_ldrb_register(raw);
-            goto a53_done;
+            else
+                result = armv7_read_arm_instr_ldrb_literal(raw);
         }
-    }
 
- a53_done:
+        else if ((op1 & b10111) == b00111)
+            result = armv7_read_arm_instr_ldrbt(raw);
 
-    return result;
+    }
+    else /*if (a == b1)*/
+    {
+        if ((op1 & b00101) == b00000 && (op1 & b10111) != b00010 && b == b0)
+            result = armv7_read_arm_instr_str_register(raw);
 
-}
+        else if ((op1 & b10111) == b00010 && b == b0)
+            result = armv7_read_arm_instr_strt(raw);
 
+        else if ((op1 & b00101) == b00001 && (op1 & b10111) != b00011 && b == b0)
+            result = armv7_read_arm_instr_ldr_register_arm(raw);
 
+        else if ((op1 & b10111) == b00011 && b == b0)
+            result = armv7_read_arm_instr_ldrt(raw);
 
+        else if ((op1 & b00101) == b00100 && (op1 & b10110) != b00110 && b == b0)
+            result = armv7_read_arm_instr_strb_register(raw);
 
+        else if ((op1 & b10110) == b00110 && b == b0)
+            result = armv7_read_arm_instr_strbt(raw);
 
+        else if ((op1 & b00101) == b00101 && (op1 & b10111) != b00111 && b == b0)
+                result = armv7_read_arm_instr_ldrb_register(raw);
 
+        else if ((op1 & b10111) == b00111 && b == b0)
+            result = armv7_read_arm_instr_ldrbt(raw);
 
+    }
 
+    return result;
 
+}
 
 
 /******************************************************************************
@@ -2291,7 +2239,7 @@ static GArchInstruction *process_armv7_arm_memory_hints_advanced_simd_instructio
             result = armv7_read_arm_instr_dsb(raw);
 
         else if (op2 == b0101)
-            result = armv7_read_arm_instr_dmd(raw);
+            result = armv7_read_arm_instr_dmb(raw);
 
         else if (op2 == b0110)
             result = armv7_read_arm_instr_isb(raw);
diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
index ec8372a..dcfd635 100644
--- a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
+++ b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
@@ -1,7 +1,6 @@
 #ifndef arm_def_tmp_h
 #define arm_def_tmp_h
 #define armv7_read_arm_instr_cps_arm(r) NULL
-#define armv7_read_arm_instr_dmd(r) NULL
 #define armv7_read_arm_instr_eret(r) NULL
 #define armv7_read_arm_instr_hvc(r) NULL
 #define armv7_read_arm_instr_isb(r) NULL
@@ -13,7 +12,6 @@
 #define armv7_read_arm_instr_ldmib_ldmed(r) NULL
 #define armv7_read_arm_instr_ldm_ldmia_ldmfd_arm(r) NULL
 #define armv7_read_arm_instr_ldm_user_registers(r) NULL
-#define armv7_read_arm_instr_ldr_register(r) NULL
 #define armv7_read_arm_instr_mrs(r) NULL
 #define armv7_read_arm_instr_mrs_banked_register(r) NULL
 #define armv7_read_arm_instr_msr_banked_register(r) NULL
diff --git a/src/arch/arm/v7/pseudo.c b/src/arch/arm/v7/pseudo.c
index 03644e2..6f2451b 100644
--- a/src/arch/arm/v7/pseudo.c
+++ b/src/arch/arm/v7/pseudo.c
@@ -601,7 +601,11 @@ bool armv7_shift_c(uint32_t x, unsigned int n, SRType type, unsigned int amount,
 
     if (type == SRType_RRX && amount != 1) return false;
 
-    if (amount == 0) return true;
+    if (amount == 0)
+    {
+        *value = 0;
+        return true;
+    }
 
     result = true;     /* Pour GCC... */
 
-- 
cgit v0.11.2-87-g4458