ARM: Add support for "SUBS PC, LR and related instructions".
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:04 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:04 +0000 (12:58 -0500)
src/arch/arm/isa/formats/branch.isa
src/arch/arm/isa/formats/data.isa
src/arch/arm/isa/insts/data.isa

index caf6f6227c0ba53be84dab0c63d43fca22b98285..45464018ebc4eef79ab24dd14a01614229b1fd3d 100644 (file)
@@ -192,8 +192,11 @@ def format Thumb32BranchesAndMiscCtrl() {{
                   case 0x3c:
                     return new WarnUnimplemented("bxj", machInst);
                   case 0x3d:
-                    return new WarnUnimplemented("subs_pc_lr_and_rel_insts",
-                                                 machInst);
+                    {
+                        const uint32_t imm32 = bits(machInst, 7, 0);
+                        return new SubsImmPclr(machInst, INTREG_PC, INTREG_LR,
+                                               imm32, false);
+                    }
                   case 0x3e:
                   case 0x3f:
                     return new WarnUnimplemented("mrs", machInst);
index 45dedff2cd0df3b21488844a94172844f9416196..eb36699c21fc3253b48497dabdfd76df32c15303 100644 (file)
 // Authors: Gabe Black
 
 def format ArmDataProcReg() {{
+    pclr = '''
+        return new %(className)ssRegPclr(machInst, %(dest)s,
+                                        %(op1)s, rm, imm5,
+                                        type);
+    '''
     instDecode = '''
           case %(opcode)#x:
             if (immShift) {
                 if (setCc) {
-                    return new %(className)sRegCc(machInst, %(dest)s, %(op1)s,
-                                                   rm, imm5, type);
+                    if (%(dest)s == INTREG_PC) {
+                        %(pclr)s
+                    } else {
+                        return new %(className)sRegCc(machInst, %(dest)s,
+                                                      %(op1)s, rm, imm5, type);
+                    }
                 } else {
                     return new %(className)sReg(machInst, %(dest)s, %(op1)s,
                                                  rm, imm5, type);
@@ -58,12 +67,26 @@ def format ArmDataProcReg() {{
             break;
     '''
 
-    def instCode(opcode, mnem, dest="rd", op1="rn"):
-        global instDecode
-        return instDecode % { "className": mnem.capitalize(),
-                              "opcode": opcode,
-                              "dest": dest,
-                              "op1": op1 }
+    def instCode(opcode, mnem, useDest = True, useOp1 = True):
+        global pclr
+        if useDest:
+            dest = "rd"
+        else:
+            dest = "INTREG_ZERO"
+        if useOp1:
+            op1 = "rn"
+        else:
+            op1 = "INTREG_ZERO"
+        global instDecode, pclrCode
+        substDict = { "className": mnem.capitalize(),
+                      "opcode": opcode,
+                      "dest": dest,
+                      "op1": op1 }
+        if useDest:
+            substDict["pclr"] = pclr % substDict
+        else:
+            substDict["pclr"] = ""
+        return instDecode % substDict
 
     decode_block = '''
     {
@@ -85,14 +108,14 @@ def format ArmDataProcReg() {{
     decode_block += instCode(0x5, "adc")
     decode_block += instCode(0x6, "sbc")
     decode_block += instCode(0x7, "rsc")
-    decode_block += instCode(0x8, "tst", dest="INTREG_ZERO")
-    decode_block += instCode(0x9, "teq", dest="INTREG_ZERO")
-    decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO")
-    decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO")
+    decode_block += instCode(0x8, "tst", useDest = False)
+    decode_block += instCode(0x9, "teq", useDest = False)
+    decode_block += instCode(0xa, "cmp", useDest = False)
+    decode_block += instCode(0xb, "cmn", useDest = False)
     decode_block += instCode(0xc, "orr")
-    decode_block += instCode(0xd, "mov", op1="INTREG_ZERO")
+    decode_block += instCode(0xd, "mov", useOp1 = False)
     decode_block += instCode(0xe, "bic")
-    decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO")
+    decode_block += instCode(0xf, "mvn", useOp1 = False)
     decode_block += '''
           default:
             return new Unknown(machInst);
@@ -102,43 +125,70 @@ def format ArmDataProcReg() {{
 }};
 
 def format ArmDataProcImm() {{
+    pclr = '''
+        return new %(className)ssImmPclr(machInst, %(dest)s,
+                                        %(op1)s, imm, false);
+    '''
+    adr = '''
+        return new AdrImm(machInst, %(dest)s, %(add)s,
+                                     imm, false);
+    '''
     instDecode = '''
+          case %(opcode)#x:
             if (setCc) {
-                return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
-                                               imm, rotC);
+                if (%(pclrInst)s && %(dest)s == INTREG_PC) {
+                    %(pclr)s
+                } else {
+                    return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
+                                                   imm, rotC);
+                }
             } else {
-                return new %(className)sImm(machInst, %(dest)s, %(op1)s,
-                                             imm, rotC);
+                if (%(adrInst)s && %(op1)s == INTREG_PC) {
+                    %(adr)s
+                } else {
+                    return new %(className)sImm(machInst, %(dest)s, %(op1)s,
+                                                 imm, rotC);
+                }
             }
             break;
     '''
 
-    def instCode(opcode, mnem, dest="rd", op1="rn"):
-        global instDecode
-        code = '''
-          case %(opcode)#x:
-        ''' + instDecode
-        return code % { "className": mnem.capitalize(),
-                        "opcode": opcode,
-                        "dest": dest,
-                        "op1": op1 }
+    def instCode(opcode, mnem, useDest = True, useOp1 = True):
+        global instDecode, pclr, adr
+        if useDest:
+            dest = "rd"
+        else:
+            dest = "INTREG_ZERO"
+        if useOp1:
+            op1 = "rn"
+        else:
+            op1 = "INTREG_ZERO"
+        substDict = { "className": mnem.capitalize(),
+                      "opcode": opcode,
+                      "dest": dest,
+                      "op1": op1,
+                      "adr": "",
+                      "adrInst": "false" }
+        if useDest:
+            substDict["pclrInst"] = "true"
+            substDict["pclr"] = pclr % substDict
+        else:
+            substDict["pclrInst"] = "false"
+            substDict["pclr"] = ""
+        return instDecode % substDict
 
-    def adrCode(opcode, mnem, dest="rd", op1="rn", add="1"):
-        global instDecode
-        code = '''
-          case %(opcode)#x:
-            if (rn == 0xf) {
-                return new AdrImm(machInst, %(dest)s, %(add)s,
-                                             imm, false);
-            } else {
-        ''' + instDecode + '''
-            }
-        '''
-        return code % { "className": mnem.capitalize(),
-                        "opcode": opcode,
-                        "dest": dest,
-                        "add": add,
-                        "op1": op1 }
+    def adrCode(opcode, mnem, add="1"):
+        global instDecode, pclr, adr
+        substDict = { "className": mnem.capitalize(),
+                      "opcode": opcode,
+                      "dest": "rd",
+                      "op1": "rn",
+                      "add": add,
+                      "pclrInst": "true",
+                      "adrInst": "true" }
+        substDict["pclr"] = pclr % substDict
+        substDict["adr"] = adr % substDict
+        return instDecode % substDict
 
     decode_block = '''
     {
@@ -159,14 +209,14 @@ def format ArmDataProcImm() {{
     decode_block += instCode(0x5, "adc")
     decode_block += instCode(0x6, "sbc")
     decode_block += instCode(0x7, "rsc")
-    decode_block += instCode(0x8, "tst", dest="INTREG_ZERO")
-    decode_block += instCode(0x9, "teq", dest="INTREG_ZERO")
-    decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO")
-    decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO")
+    decode_block += instCode(0x8, "tst", useDest = False)
+    decode_block += instCode(0x9, "teq", useDest = False)
+    decode_block += instCode(0xa, "cmp", useDest = False)
+    decode_block += instCode(0xb, "cmn", useDest = False)
     decode_block += instCode(0xc, "orr")
-    decode_block += instCode(0xd, "mov", op1="INTREG_ZERO")
+    decode_block += instCode(0xd, "mov", useOp1 = False)
     decode_block += instCode(0xe, "bic")
-    decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO")
+    decode_block += instCode(0xf, "mvn", useOp1 = False)
     decode_block += '''
           default:
             return new Unknown(machInst);
index 02ecd6b4c4a62c6db9f716b0ae27c5993326930f..69e813d2541a4d559556ff9a2e91280300640a08 100644 (file)
@@ -98,8 +98,8 @@ let {{
     regOp2 = "shift_rm_imm(Op2, shiftAmt, shiftType, CondCodes<29:>)"
     regRegOp2 = "shift_rm_rs(Op2, Shift<7:0>, shiftType, CondCodes<29:>)"
 
-    def buildImmDataInst(mnem, code, flagType = "logic"):
-        global header_output, decoder_output, exec_output
+    def buildImmDataInst(mnem, code, flagType = "logic", \
+                         suffix = "Imm", buildCc = True):
         cCode = carryCode[flagType]
         vCode = overflowCode[flagType]
         negBit = 31
@@ -114,22 +114,26 @@ let {{
                 "negBit": negBit
             }
         immCode = secondOpRe.sub(immOp2, code)
-        immIop = InstObjParams(mnem, mnem.capitalize() + "Imm", "DataImmOp",
+        immIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataImmOp",
                                {"code" : immCode,
                                 "predicate_test": predicateTest})
-        immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + "ImmCc",
+        immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc",
                                  "DataImmOp",
                                  {"code" : immCode + immCcCode,
                                   "predicate_test": predicateTest})
-        header_output += DataImmDeclare.subst(immIop) + \
-                         DataImmDeclare.subst(immIopCc)
-        decoder_output += DataImmConstructor.subst(immIop) + \
-                          DataImmConstructor.subst(immIopCc)
-        exec_output += PredOpExecute.subst(immIop) + \
-                       PredOpExecute.subst(immIopCc)
-
-    def buildRegDataInst(mnem, code, flagType = "logic"):
-        global header_output, decoder_output, exec_output
+
+        def subst(iop):
+            global header_output, decoder_output, exec_output
+            header_output += DataImmDeclare.subst(iop)
+            decoder_output += DataImmConstructor.subst(iop)
+            exec_output += PredOpExecute.subst(iop)
+
+        subst(immIop)
+        if buildCc:
+            subst(immIopCc)
+
+    def buildRegDataInst(mnem, code, flagType = "logic", \
+                         suffix = "Reg", buildCc = True):
         cCode = carryCode[flagType]
         vCode = overflowCode[flagType]
         negBit = 31
@@ -144,22 +148,26 @@ let {{
                 "negBit": negBit
             }
         regCode = secondOpRe.sub(regOp2, code)
-        regIop = InstObjParams(mnem, mnem.capitalize() + "Reg", "DataRegOp",
+        regIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegOp",
                                {"code" : regCode,
                                 "predicate_test": predicateTest})
-        regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + "RegCc",
+        regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc",
                                  "DataRegOp",
                                  {"code" : regCode + regCcCode,
                                   "predicate_test": predicateTest})
-        header_output += DataRegDeclare.subst(regIop) + \
-                         DataRegDeclare.subst(regIopCc)
-        decoder_output += DataRegConstructor.subst(regIop) + \
-                          DataRegConstructor.subst(regIopCc)
-        exec_output += PredOpExecute.subst(regIop) + \
-                       PredOpExecute.subst(regIopCc)
-
-    def buildRegRegDataInst(mnem, code, flagType = "logic"):
-        global header_output, decoder_output, exec_output
+
+        def subst(iop):
+            global header_output, decoder_output, exec_output
+            header_output += DataRegDeclare.subst(iop)
+            decoder_output += DataRegConstructor.subst(iop)
+            exec_output += PredOpExecute.subst(iop)
+
+        subst(regIop)
+        if buildCc:
+            subst(regIopCc)
+
+    def buildRegRegDataInst(mnem, code, flagType = "logic", \
+                            suffix = "RegReg", buildCc = True):
         cCode = carryCode[flagType]
         vCode = overflowCode[flagType]
         negBit = 31
@@ -174,53 +182,72 @@ let {{
                 "negBit": negBit
             }
         regRegCode = secondOpRe.sub(regRegOp2, code)
-        regRegIop = InstObjParams(mnem, mnem.capitalize() + "RegReg",
+        regRegIop = InstObjParams(mnem, mnem.capitalize() + suffix,
                                   "DataRegRegOp",
                                   {"code" : regRegCode,
                                    "predicate_test": predicateTest})
         regRegIopCc = InstObjParams(mnem + "s",
-                                    mnem.capitalize() + "RegRegCc",
+                                    mnem.capitalize() + suffix + "Cc",
                                     "DataRegRegOp",
                                     {"code" : regRegCode + regRegCcCode,
                                      "predicate_test": predicateTest})
-        header_output += DataRegRegDeclare.subst(regRegIop) + \
-                         DataRegRegDeclare.subst(regRegIopCc)
-        decoder_output += DataRegRegConstructor.subst(regRegIop) + \
-                          DataRegRegConstructor.subst(regRegIopCc)
-        exec_output += PredOpExecute.subst(regRegIop) + \
-                       PredOpExecute.subst(regRegIopCc)
-
-    def buildDataInst(mnem, code, flagType = "logic"):
-        buildImmDataInst(mnem, code, flagType)
-        buildRegDataInst(mnem, code, flagType)
-        buildRegRegDataInst(mnem, code, flagType)
-
-    buildDataInst("and", "AIWDest = resTemp = Op1 & secondOp;")
-    buildDataInst("eor", "AIWDest = resTemp = Op1 ^ secondOp;")
-    buildDataInst("sub", "AIWDest = resTemp = Op1 - secondOp;", "sub")
-    buildDataInst("rsb", "AIWDest = resTemp = secondOp - Op1;", "rsb")
-    buildDataInst("add", "AIWDest = resTemp = Op1 + secondOp;", "add")
+
+        def subst(iop):
+            global header_output, decoder_output, exec_output
+            header_output += DataRegRegDeclare.subst(iop)
+            decoder_output += DataRegRegConstructor.subst(iop)
+            exec_output += PredOpExecute.subst(iop)
+
+        subst(regRegIop)
+        if buildCc:
+            subst(regRegIopCc)
+
+    def buildDataInst(mnem, code, flagType = "logic", \
+                      aiw = True, regRegAiw = True,
+                      subsPcLr = True):
+        regRegCode = instCode = code
+        if aiw:
+            instCode = "AIW" + instCode
+            if regRegAiw:
+                regRegCode = "AIW" + regRegCode
+
+        buildImmDataInst(mnem, instCode, flagType)
+        buildRegDataInst(mnem, instCode, flagType)
+        buildRegRegDataInst(mnem, regRegCode, flagType)
+        if subsPcLr:
+            code += '''
+            uint32_t newCpsr =
+                cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true);
+            Cpsr = ~CondCodesMask & newCpsr;
+            CondCodes = CondCodesMask & newCpsr;
+            '''
+            buildImmDataInst(mnem + 's', code, flagType,
+                             suffix = "ImmPclr", buildCc = False)
+            buildRegDataInst(mnem + 's', code, flagType,
+                             suffix = "RegPclr", buildCc = False)
+
+    buildDataInst("and", "Dest = resTemp = Op1 & secondOp;")
+    buildDataInst("eor", "Dest = resTemp = Op1 ^ secondOp;")
+    buildDataInst("sub", "Dest = resTemp = Op1 - secondOp;", "sub")
+    buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb")
+    buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add")
     buildImmDataInst("adr", '''
-                               AIWDest = resTemp = (readPC(xc) & ~0x3) +
+                               Dest = resTemp = (readPC(xc) & ~0x3) +
                                (op1 ? secondOp : -secondOp);
                             ''')
-    buildDataInst("adc", "AIWDest = resTemp = Op1 + secondOp + %s;" % oldC,
-                  "add")
-    buildDataInst("sbc", "AIWDest = resTemp = Op1 - secondOp - !%s;" % oldC,
-                  "sub")
-    buildDataInst("rsc", "AIWDest = resTemp = secondOp - Op1 - !%s;" % oldC,
-                  "rsb")
-    buildDataInst("tst", "resTemp = Op1 & secondOp;")
-    buildDataInst("teq", "resTemp = Op1 ^ secondOp;")
-    buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub")
-    buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add")
-    buildDataInst("orr", "AIWDest = resTemp = Op1 | secondOp;")
-    buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;")
-    buildImmDataInst("mov", "AIWDest = resTemp = secondOp;")
-    buildRegDataInst("mov", "AIWDest = resTemp = secondOp;")
-    buildRegRegDataInst("mov", "Dest = resTemp = secondOp;")
-    buildDataInst("bic", "AIWDest = resTemp = Op1 & ~secondOp;")
-    buildDataInst("mvn", "AIWDest = resTemp = ~secondOp;")
+    buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add")
+    buildDataInst("sbc", "Dest = resTemp = Op1 - secondOp - !%s;" % oldC, "sub")
+    buildDataInst("rsc", "Dest = resTemp = secondOp - Op1 - !%s;" % oldC, "rsb")
+    buildDataInst("tst", "resTemp = Op1 & secondOp;", aiw = False)
+    buildDataInst("teq", "resTemp = Op1 ^ secondOp;", aiw = False)
+    buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub", aiw = False)
+    buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add", aiw = False)
+    buildDataInst("orr", "Dest = resTemp = Op1 | secondOp;")
+    buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;", aiw = False)
+    buildDataInst("mov", "Dest = resTemp = secondOp;", regRegAiw = False)
+    buildDataInst("bic", "Dest = resTemp = Op1 & ~secondOp;")
+    buildDataInst("mvn", "Dest = resTemp = ~secondOp;")
     buildDataInst("movt",
-            "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);")
+                  "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);",
+                  aiw = False)
 }};