ARM: Decode the load halfword, memory hints instructions for 32 bit Thumb.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:09 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:09 +0000 (12:58 -0500)
src/arch/arm/isa/decoder/thumb.isa
src/arch/arm/isa/formats/mem.isa

index e8e2d59199bddb31fff35c30dbd84c411312c838..ab431303c6d20215713cbf89bbb33173f0d0fd2e 100644 (file)
                 }
                 0x1: decode HTOPCODE_6_5 {
                     0x0: WarnUnimpl::Load_byte_memory_hints();
-                    0x1: WarnUnimpl::Load_halfword_memory_hints();
+                    0x1: LoadHalfwordMemoryHints::loadHalfwordMemoryHints();
                     0x2: Thumb32LoadWord::thumb32LoadWord();
                     0x3: WarnUnimpl::undefined();
                 }
index 6b36e39fb60df59ebe78171e739e4518b5e2cf4e..6b511362ff32c7b558d255907dab08dd47e76a36 100644 (file)
@@ -468,6 +468,180 @@ def format Thumb32StoreSingle() {{
     decode_block = decode % classNames
 }};
 
+def format LoadHalfwordMemoryHints() {{
+    decode = '''
+    {
+        const uint32_t op1 = bits(machInst, 24, 23);
+        const uint32_t op2 = bits(machInst, 11, 6);
+        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
+        const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
+        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
+        const uint32_t imm12 = bits(machInst, 11, 0);
+        const uint32_t imm8 = bits(machInst, 7, 0);
+        bool pldw = bits(machInst, 21);
+        const uint32_t imm2 = bits(machInst, 5, 4);
+        if (rn == 0xf) {
+            if (rt == 0xf) {
+                if (bits(op1, 1) == 1) {
+                    // Unallocated memory hint
+                    return new NopInst(machInst);
+                } else {
+                    return new Unknown(machInst);
+                }
+            } else {
+                if (bits(op1, 1) == 1) {
+                    if (bits(machInst, 23)) {
+                        return new %(ldrsh_lit_u)s(machInst, rt, INTREG_PC,
+                                                   true, imm12);
+                    } else {
+                        return new %(ldrsh_lit)s(machInst, rt, INTREG_PC,
+                                                 false, imm12);
+                    }
+                } else {
+                    if (bits(machInst, 23)) {
+                        return new %(ldrh_lit_u)s(machInst, rt, INTREG_PC,
+                                                  true, imm12);
+                    } else {
+                        return new %(ldrh_lit)s(machInst, rt, INTREG_PC,
+                                                false, imm12);
+                    }
+                }
+            }
+        } else if (rt == 0xf) {
+            switch (op1) {
+              case 0x0:
+                if (op2 == 0x0) {
+                    if (pldw) {
+                        return new %(pldw_radd)s(machInst, INTREG_ZERO,
+                                                 rn, true, imm2, LSL, rm);
+                    } else {
+                        return new %(pld_radd)s(machInst, INTREG_ZERO,
+                                                rn, true, imm2, LSL, rm);
+                    }
+                } else if (bits(op2, 5, 2) == 0xc) {
+                    if (pldw) {
+                        return new %(pldw_isub)s(machInst, INTREG_ZERO,
+                                                 rn, false, imm8);
+                    } else {
+                        return new %(pld_isub)s(machInst, INTREG_ZERO,
+                                                rn, false, imm8);
+                    }
+                }
+                break;
+              case 0x1:
+                if (pldw) {
+                    return new %(pldw_iadd)s(machInst, INTREG_ZERO,
+                                             rn, true, imm12);
+                } else {
+                    return new %(pld_iadd)s(machInst, INTREG_ZERO,
+                                            rn, true, imm12);
+                }
+              case 0x2:
+                if (op2 == 0x0 || bits(op2, 5, 2) == 0xc) {
+                    // Unallocated memory hint
+                    return new NopInst(machInst);
+                }
+                break;
+              case 0x3:
+                return new NopInst(machInst);
+            }
+            return new Unknown(machInst);
+        } else {
+            switch (op1) {
+              case 0x0:
+                if (op2 == 0) {
+                    return new %(ldrh_radd)s(machInst, rt, rn, true,
+                                             imm2, LSL, rm);
+                } else if (bits(op2, 5, 2) == 0xe) {
+                    return new %(ldrht)s(machInst, rt, rn, true, imm8);
+                } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) {
+                    const uint32_t puw = bits(machInst, 10, 8);
+                    switch (puw) {
+                      case 0x1:
+                        return new %(ldrh_iw)s(machInst, rt,
+                                               rn, false, imm8);
+                      case 0x3:
+                        return new %(ldrh_iuw)s(machInst, rt,
+                                                rn, true, imm8);
+                      case 0x4:
+                        return new %(ldrh_ip)s(machInst, rt,
+                                               rn, false, imm8);
+                      case 0x5:
+                        return new %(ldrh_ipw)s(machInst, rt,
+                                                rn, false, imm8);
+                      case 0x7:
+                        return new %(ldrh_ipuw)s(machInst, rt,
+                                                 rn, true, imm8);
+                    }
+                }
+                break;
+              case 0x1:
+                return new %(ldrh_iadd)s(machInst, rt, rn, true, imm12);
+              case 0x2:
+                if (op2 == 0) {
+                    return new %(ldrsh_radd)s(machInst, rt, rn, true,
+                                              imm2, LSL, rm);
+                } else if (bits(op2, 5, 2) == 0xe) {
+                    return new %(ldrsht)s(machInst, rt, rn, true, imm8);
+                } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) {
+                    const uint32_t puw = bits(machInst, 10, 8);
+                    switch (puw) {
+                      case 0x1:
+                        return new %(ldrsh_iw)s(machInst, rt,
+                                                rn, false, imm8);
+                      case 0x3:
+                        return new %(ldrsh_iuw)s(machInst, rt,
+                                                 rn, true, imm8);
+                      case 0x4:
+                        return new %(ldrsh_ip)s(machInst, rt,
+                                                rn, false, imm8);
+                      case 0x5:
+                        return new %(ldrsh_ipw)s(machInst, rt,
+                                                 rn, false, imm8);
+                      case 0x7:
+                        return new %(ldrsh_ipuw)s(machInst, rt,
+                                                  rn, true, imm8);
+                    }
+                }
+                break;
+              case 0x3:
+                return new %(ldrsh_iadd)s(machInst, rt, rn, true, imm12);
+            }
+            return new Unknown(machInst);
+        }
+    }
+    '''
+    substDict = {
+        "ldrsh_lit_u" : loadImmClassName(False, True, False, 2, True),
+        "ldrsh_lit" : loadImmClassName(False, False, False, 2, True),
+        "ldrh_lit_u" : loadImmClassName(False, True, False, 2),
+        "ldrh_lit" : loadImmClassName(False, False, False, 2),
+        "ldrsh_radd" : loadRegClassName(False, True, False, 2, True),
+        "ldrh_radd" : loadRegClassName(False, True, False, 2),
+        "ldrsh_iw" : loadImmClassName(True, False, True, 2, True),
+        "ldrsh_iuw" : loadImmClassName(True, True, True, 2, True),
+        "ldrsh_ip" : loadImmClassName(False, False, False, 2, True),
+        "ldrsh_ipw" : loadImmClassName(False, False, True, 2, True),
+        "ldrsh_ipuw" : loadImmClassName(False, True, True, 2, True),
+        "ldrsh_iadd" : loadImmClassName(False, True, False, 2, True),
+        "ldrh_iw" : loadImmClassName(True, False, True, 2),
+        "ldrh_iuw" : loadImmClassName(True, True, True, 2),
+        "ldrh_ip" : loadImmClassName(False, False, False, 2),
+        "ldrh_ipw" : loadImmClassName(False, False, True, 2),
+        "ldrh_ipuw" : loadImmClassName(False, True, True, 2),
+        "ldrh_iadd" : loadImmClassName(False, True, False, 2),
+        "ldrht" : loadImmClassName(False, True, False, 2, user=True),
+        "ldrsht" : loadImmClassName(False, True, False, 2, True, user=True),
+        "pldw_radd" : "PLDW_" + loadRegClassName(False, True, False, 1),
+        "pld_radd" : "PLD_" + loadRegClassName(False, True, False, 1),
+        "pldw_isub" : "PLDW_" + loadImmClassName(False, False, False, 1),
+        "pld_isub" : "PLD_" + loadImmClassName(False, False, False, 1),
+        "pldw_iadd" : "PLDW_" + loadImmClassName(False, True, False, 1),
+        "pld_iadd" : "PLD_" + loadImmClassName(False, True, False, 1)
+    }
+    decode_block = decode % substDict
+}};
+
 def format Thumb16MemReg() {{
     decode = '''
     {