ARM: Refactor thumb decoding 61/157661/2
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 21 Feb 2017 08:47:27 +0000 (11:47 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 27 Nov 2017 07:39:41 +0000 (10:39 +0300)
Change-Id: Id30ebfcd60afa668966eb7516307abba251f299a
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
modules/arch/arm/probes/decode_thumb.c

index a35f262c0714a456490bc8f38fa41f810584e022..34a343445cd9cebfd5ef1833ec6c7a8221c04035 100644 (file)
@@ -138,7 +138,14 @@ static int t32_ldrd_strd(thumb_insn_t insn, struct decode_info *info)
        return 0;
 }
 
-static int t32_b1110_100x_x1(thumb_insn_t insn, struct decode_info *info)
+/* load/store multiple */
+static int t32_1110_100x_x0(thumb_insn_t insn, struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* load/store dual, load/store exclusive, table branch */
+static int t32_1110_100x_x1(thumb_insn_t insn, struct decode_info *info)
 {
        /* check PW bits */
        if (insn.hw1 & 0x120)
@@ -147,11 +154,15 @@ static int t32_b1110_100x_x1(thumb_insn_t insn, struct decode_info *info)
        return thumb_not_implement(insn, info);
 }
 
-static int t32_b1110_100(thumb_insn_t insn, struct decode_info *info)
+/* data-processing (shifled register) */
+static int t32_1110_101(thumb_insn_t insn, struct decode_info *info)
 {
-       if (GET_BIT(insn.hw1, 6))
-               return t32_b1110_100x_x1(insn, info);
+       return thumb_not_implement(insn, info);
+}
 
+/* coprocessor, advanced SIMD, and floating-point instructions */
+static int t32_1110_11(thumb_insn_t insn, struct decode_info *info)
+{
        return thumb_not_implement(insn, info);
 }
 
@@ -193,45 +204,182 @@ static int t32_branch(thumb_insn_t insn, struct decode_info *info)
        return 0;
 }
 
-static decode_handler_t table_branches[8] = {
-       /* hw2[14 12 0] */
-       /* Bc   0  0 0  */      thumb_not_implement,
-       /* Bc   0  0 1  */      thumb_not_implement,
-       /* B    0  1 0  */      t32_branch,
-       /* B    0  1 1  */      t32_branch,
-       /* BLX  1  0 0  */      t32_branch,
-       /* res  1  0 1  */      thumb_unpredictable,
-       /* BL   1  1 0  */      t32_branch,
-       /* BL   1  1 1  */      t32_branch,
+/* data-processing (modified immediate) */
+static int t32_1111_0x0x_xxxx_xxxx_0(thumb_insn_t insn,
+                                     struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* data-processing (plain binary immediate) */
+static int t32_1111_0x1x_xxxx_xxxx_0(thumb_insn_t insn,
+                                     struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* conditional branch, move to blanked or special register */
+static int t32_1111_0011_100x_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* change processor state, and hints */
+static int t32_1111_0011_1010_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* miscellaneous control instructions */
+static int t32_1111_0011_1011_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* branch and exchange jazelle */
+static int t32_1111_0011_1100_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* exeption return  */
+static int t32_1111_0011_1101_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+/* move from banked or special register */
+static int t32_1111_0011_111x_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return thumb_not_implement(insn, info);
+}
+
+static decode_handler_t t32_1111_0011_1XXX_xxxx_10x0[8] = {
+       /* 000 */       t32_1111_0011_100x_xxxx_10x0,
+       /* 001 */       t32_1111_0011_100x_xxxx_10x0,
+       /* 010 */       t32_1111_0011_1010_xxxx_10x0,
+       /* 011 */       t32_1111_0011_1011_xxxx_10x0,
+       /* 100 */       t32_1111_0011_1100_xxxx_10x0,
+       /* 101 */       t32_1111_0011_1101_xxxx_10x0,
+       /* 110 */       t32_1111_0011_111x_xxxx_10x0,
+       /* 111 */       t32_1111_0011_111x_xxxx_10x0,
 };
 
 
+static int t32_1111_0xxx_xxxx_xxxx_10x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       unsigned char op = GET_FIELD(insn.hw1, 4, 7);
+
+       if (GET_FIELD(op, 3, 3) == 0x7) {
+               if (GET_BIT(op, 6) == 0) {
+                       unsigned char val = GET_FIELD(op, 0, 3);
 
-static int t32_b1111_0xxx_xxxx_xxxx_1(thumb_insn_t insn,
+                       return t32_1111_0011_1XXX_xxxx_10x0[val](insn, info);
+               } else {
+                       /* hypervisor call and secure monitor call */
+                       return thumb_not_implement(insn, info);
+               }
+       } else {
+               /* conditional branch */
+               return thumb_not_implement(insn, info);
+       }
+}
+
+static int t32_1111_0xxx_xxxx_xxxx_10x1(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return t32_branch(insn, info);
+}
+
+static int t32_1111_0xxx_xxxx_xxxx_11x0(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return t32_branch(insn, info);
+}
+
+static int t32_1111_0xxx_xxxx_xxxx_11x1(thumb_insn_t insn,
+                                       struct decode_info *info)
+{
+       return t32_branch(insn, info);
+}
+
+static decode_handler_t table_1111_0xxx_xxxx_xxxx_1XXX[8] = {
+       /* 000 */       t32_1111_0xxx_xxxx_xxxx_10x0,
+       /* 001 */       t32_1111_0xxx_xxxx_xxxx_10x1,
+       /* 010 */       t32_1111_0xxx_xxxx_xxxx_10x0,
+       /* 011 */       t32_1111_0xxx_xxxx_xxxx_10x1,
+       /* 100 */       t32_1111_0xxx_xxxx_xxxx_11x0,
+       /* 101 */       t32_1111_0xxx_xxxx_xxxx_11x1,
+       /* 110 */       t32_1111_0xxx_xxxx_xxxx_11x0,
+       /* 111 */       t32_1111_0xxx_xxxx_xxxx_11x1,
+};
+
+/* branches and miscellaneous control */
+static int t32_1111_0xxx_xxxx_xxxx_1(thumb_insn_t insn,
                                      struct decode_info *info)
 {
-       u32 s = GET_BIT(insn.hw2, 14) << 2 |
-               GET_BIT(insn.hw2, 12) << 1 |
-               GET_BIT(insn.hw2, 0);
+       unsigned char op1 = GET_FIELD(insn.hw2, 12, 3);
 
-       return table_branches[s](insn, info);
+       /* check op1 bits hw1[1111 0??? ???? ???? 1xxx] */
+       return table_1111_0xxx_xxxx_xxxx_1XXX[op1](insn, info);
 }
 
-static int b111(thumb_insn_t insn, struct decode_info *info)
+static int t32_1110_1(thumb_insn_t insn, struct decode_info *info)
 {
-       /* hw1[111x xxx? ???? ????] */
-       switch (GET_FIELD(insn.hw1, 9, 4)) {
-       case 0b0100:
-               return t32_b1110_100(insn, info);
+       unsigned char op2 = GET_FIELD(insn.hw1, 4, 7);
+
+       if (GET_BIT(op2, 6) == 0) {
+               if (GET_BIT(op2, 5) == 0) {
+                       if (GET_BIT(op2, 2) == 0)
+                               return t32_1110_100x_x0(insn, info);
+                       else
+                               return t32_1110_100x_x1(insn, info);
+               } else {
+                       return t32_1110_101(insn, info);
+               }
+       } else {
+               return t32_1110_11(insn, info);
        }
 
-       /* [1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx] */
-       if (GET_FIELD(insn.hw1, 11, 2) == 0b10 && GET_BIT(insn.hw2, 15) == 1)
-               return t32_b1111_0xxx_xxxx_xxxx_1(insn, info);
+       return thumb_not_implement(insn, info);
+}
+
+static int t32_1111_0(thumb_insn_t insn, struct decode_info *info)
+{
+       if (GET_BIT(insn.hw2, 15) == 0) {
+               if (GET_BIT(insn.hw1, 9) == 0)
+                       return t32_1111_0x0x_xxxx_xxxx_0(insn, info);
+               else
+                       return t32_1111_0x1x_xxxx_xxxx_0(insn, info);
+       } else {
+               /* [1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx] */
+               return t32_1111_0xxx_xxxx_xxxx_1(insn, info);
+       }
 
        return thumb_not_implement(insn, info);
 }
 
+decode_handler_t table_111x_x[4] = {
+       /* 00 | 16-bit */       thumb_not_implement,
+       /* 01 | 32-bit */       t32_1110_1,
+       /* 10 | 32-bit */       t32_1111_0,
+       /* 11 | 32-bit */       thumb_not_implement,
+};
+
+static int b111(thumb_insn_t insn, struct decode_info *info)
+{
+       unsigned char op1 = GET_FIELD(insn.hw1, 11, 2);
+
+       /* check op1 bits hw1[111x x??? ???? ????] */
+       return table_111x_x[op1](insn, info);
+}
 
 decode_handler_t table_xxx[8] = {
        /* 000 */       thumb_not_implement,