ARM: Identify branches as conditional or unconditional and direct or indirect.
authorAli Saidi <Ali.Saidi@ARM.com>
Fri, 18 Mar 2011 00:20:20 +0000 (19:20 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Fri, 18 Mar 2011 00:20:20 +0000 (19:20 -0500)
src/arch/arm/insts/branch.hh
src/arch/arm/isa/insts/branch.isa
src/arch/arm/isa/templates/branch.isa
src/arch/arm/predecoder.hh
src/arch/arm/types.hh

index fbdd10d68b233ed242d51339f25a9b578ff05887..0e33a92146367397029e066ebfc23acc6761a4f7 100644 (file)
@@ -57,6 +57,7 @@ class BranchImm : public PredOp
               int32_t _imm) :
         PredOp(mnem, _machInst, __opClass), imm(_imm)
     {}
+
 };
 
 // Conditionally Branch to a target computed with an immediate
index d8ea2118e860d2fc503579fe4310d978dcc56f50..84b9bb720396116e9eedd62521eb7464ffd94175 100644 (file)
@@ -48,6 +48,8 @@ let {{
         bCode = '''
         NPC = (uint32_t)(PC + imm);
         '''
+        br_tgt_code = '''pcs.instNPC(branchPC.instPC() + imm);'''
+        instFlags = ["IsDirectControl"]
         if (link):
             bCode += '''
                 if (Thumb)
@@ -55,12 +57,15 @@ let {{
                 else
                     LR = PC - 4;
             '''
+            instFlags += ["IsCall"]
+
 
         bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
-                             {"code": bCode,
-                              "predicate_test": predicateTest})
+                             {"code": bCode, "predicate_test": predicateTest,
+                             "brTgtCode" : br_tgt_code}, instFlags)
         header_output += BranchImmCondDeclare.subst(bIop)
-        decoder_output += BranchImmCondConstructor.subst(bIop)
+        decoder_output += BranchImmCondConstructor.subst(bIop) + \
+                       BranchTarget.subst(bIop)
         exec_output += PredOpExecute.subst(bIop)
 
     # BX, BLX
@@ -81,15 +86,22 @@ let {{
             # Since we're switching ISAs, the target ISA will be the opposite
             # of the current ISA. Thumb is whether the target is ARM.
             newPC = '(Thumb ? (roundDown(PC, 4) + imm) : (PC + imm))'
+            br_tgt_code = '''
+            pcs.instNPC((branchPC.thumb() ? (roundDown(branchPC.instPC(),4) + imm) :
+                                (branchPC.instPC() + imm)));
+            '''
             base = "BranchImmCond"
             declare = BranchImmCondDeclare
             constructor = BranchImmCondConstructor
+            instFlags = ["IsDirectControl"]
         else:
             Name += "Reg"
             newPC = 'Op1'
+            br_tgt_code = ''
             base = "BranchRegCond"
             declare = BranchRegCondDeclare
             constructor = BranchRegCondConstructor
+            instFlags = ["IsIndirectControl"]
         if link and imm:
             linkStr = '''
                 // The immediate version of the blx thumb instruction
@@ -100,6 +112,7 @@ let {{
                 else
                     LR = PC - 4;
             '''
+            instFlags += ["IsCall"]
         elif link:
             linkStr = '''
                 if (Thumb)
@@ -107,14 +120,18 @@ let {{
                 else
                     LR = PC - 4;
             '''
+            instFlags += ["IsCall"]
         else:
             linkStr = ""
+            instFlags += ["IsReturn"]
 
         if imm and link: #blx with imm
             branchStr = '''
                 NextThumb = !Thumb;
                 NPC = %(newPC)s;
             '''
+            br_tgt_code = '''pcs.nextThumb(!branchPC.thumb());\n''' + \
+                          br_tgt_code
         else:
             branchStr = "IWNPC = %(newPC)s;"
         branchStr = branchStr % { "newPC" : newPC }
@@ -123,11 +140,13 @@ let {{
                           "newPC": newPC,
                           "branch": branchStr}
         blxIop = InstObjParams(mnem, Name, base,
-                               {"code": code,
-                                "predicate_test": predicateTest})
+                               {"code": code, "brTgtCode" : br_tgt_code,
+                                "predicate_test": predicateTest}, instFlags)
         header_output += declare.subst(blxIop)
         decoder_output += constructor.subst(blxIop)
         exec_output += PredOpExecute.subst(blxIop)
+        if imm:
+            decoder_output += BranchTarget.subst(blxIop)
 
     #Ignore BXJ for now
 
@@ -136,7 +155,8 @@ let {{
         code = 'NPC = (uint32_t)(PC + imm);\n'
         predTest = "Op1 %(test)s 0" % {"test": test}
         iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
-                            {"code": code, "predicate_test": predTest})
+                            {"code": code, "predicate_test": predTest},
+                            ["IsIndirectControl"])
         header_output += BranchImmRegDeclare.subst(iop)
         decoder_output += BranchImmRegConstructor.subst(iop)
         exec_output += PredOpExecute.subst(iop)
@@ -164,7 +184,8 @@ let {{
         iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
                             {'ea_code': eaCode,
                              'memacc_code': accCode,
-                             'predicate_test': predicateTest})
+                             'predicate_test': predicateTest},
+                             ["IsIndirectControl"])
         header_output += BranchTableDeclare.subst(iop)
         decoder_output += BranchRegRegConstructor.subst(iop)
         exec_output += LoadExecute.subst(iop) + \
index d1f581f516dd04836c860b42f58758c9196a5e23..6abf76963704355e1d13ddcd854f631129a7f373 100644 (file)
@@ -57,7 +57,11 @@ def template BranchImmConstructor {{
             for (int x = 0; x < _numDestRegs; x++) {
                 _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
             }
+            flags[IsCondControl] = true;
+        } else {
+            flags[IsUncondControl] = true;
         }
+
     }
 }};
 
@@ -69,6 +73,7 @@ class %(class_name)s : public %(base_class)s
         %(class_name)s(ExtMachInst machInst, int32_t _imm,
                        ConditionCode _condCode);
         %(BasicExecDeclare)s
+        ArmISA::PCState branchTarget(const ArmISA::PCState &branchPC) const;
 };
 }};
 
@@ -84,6 +89,9 @@ def template BranchImmCondConstructor {{
             for (int x = 0; x < _numDestRegs; x++) {
                 _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
             }
+            flags[IsCondControl] = true;
+        } else {
+            flags[IsUncondControl] = true;
         }
     }
 }};
@@ -108,6 +116,9 @@ def template BranchRegConstructor {{
             for (int x = 0; x < _numDestRegs; x++) {
                 _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
             }
+            flags[IsCondControl] = true;
+        } else {
+            flags[IsUncondControl] = true;
         }
     }
 }};
@@ -135,6 +146,9 @@ def template BranchRegCondConstructor {{
             for (int x = 0; x < _numDestRegs; x++) {
                 _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
             }
+            flags[IsCondControl] = true;
+        } else {
+            flags[IsUncondControl] = true;
         }
     }
 }};
@@ -176,6 +190,9 @@ def template BranchRegRegConstructor {{
             for (int x = 0; x < _numDestRegs; x++) {
                 _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
             }
+            flags[IsCondControl] = true;
+        } else {
+            flags[IsUncondControl] = true;
         }
     }
 }};
@@ -202,6 +219,26 @@ def template BranchImmRegConstructor {{
             for (int x = 0; x < _numDestRegs; x++) {
                 _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
             }
+            flags[IsCondControl] = true;
+        } else {
+            flags[IsUncondControl] = true;
         }
     }
 }};
+
+def template BranchTarget {{
+
+    ArmISA::PCState
+    %(class_name)s::branchTarget(const ArmISA::PCState &branchPC) const
+    {
+        %(op_decl)s;
+        %(op_rd)s;
+
+        ArmISA::PCState pcs = branchPC;
+        %(brTgtCode)s
+        pcs.advance();
+        return pcs;
+    }
+}};
+
+
index 511bc29bc9427cbece8aa02f0df9712eeb4b81e3..08e1676c0df77d4a78e3a33da24cc781ea8ade19 100644 (file)
@@ -128,17 +128,17 @@ namespace ArmISA
                 outOfBytes = true;
         }
 
-        bool needMoreBytes()
+        bool needMoreBytes() const
         {
             return outOfBytes;
         }
 
-        bool extMachInstReady()
+        bool extMachInstReady() const
         {
             return emiReady;
         }
 
-        int getInstSize()
+        int getInstSize() const
         {
             return (!emi.thumb || emi.bigThumb) ? 4 : 2;
         }
@@ -151,6 +151,7 @@ namespace ArmISA
             pc.npc(pc.pc() + getInstSize());
             predAddrValid = true;
             predAddr = pc.pc() + getInstSize();
+            pc.size(getInstSize());
             emi = 0;
             emiReady = false;
             return thisEmi;
index e6865e280062ecf8c454df4427ca31acc3956a2c..b4ef07d8a2308893ddc24320eda20e08eb59320d 100644 (file)
@@ -203,6 +203,7 @@ namespace ArmISA
         uint8_t flags;
         uint8_t nextFlags;
         uint8_t forcedItStateValue;
+        uint8_t _size;
         bool forcedItStateValid;
       public:
         PCState() : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
@@ -248,6 +249,16 @@ namespace ArmISA
                 nextFlags &= ~ThumbBit;
         }
 
+        void size(uint8_t s) { _size = s; }
+        uint8_t size() const { return _size; }
+
+        bool
+        branching() const
+        {
+            return ((this->pc() + this->size()) != this->npc());
+        }
+
+
         bool
         jazelle() const
         {
@@ -392,6 +403,7 @@ namespace ArmISA
         {
             Base::serialize(os);
             SERIALIZE_SCALAR(flags);
+            SERIALIZE_SCALAR(_size);
             SERIALIZE_SCALAR(nextFlags);
             SERIALIZE_SCALAR(forcedItStateValue);
             SERIALIZE_SCALAR(forcedItStateValid);
@@ -402,6 +414,7 @@ namespace ArmISA
         {
             Base::unserialize(cp, section);
             UNSERIALIZE_SCALAR(flags);
+            UNSERIALIZE_SCALAR(_size);
             UNSERIALIZE_SCALAR(nextFlags);
             UNSERIALIZE_SCALAR(forcedItStateValue);
             UNSERIALIZE_SCALAR(forcedItStateValid);