diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2011-03-17 19:20:20 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2011-03-17 19:20:20 -0500 |
commit | 5480ec798aba313a03c0760d88aeadff1037f48d (patch) | |
tree | 85728e51fa46ecc7b969cac5dd23fcd0b4f371e9 | |
parent | 887e9e2b99deaddd669713f47da0642e6f6cb0c5 (diff) | |
download | gem5-5480ec798aba313a03c0760d88aeadff1037f48d.tar.xz |
ARM: Identify branches as conditional or unconditional and direct or indirect.
-rw-r--r-- | src/arch/arm/insts/branch.hh | 1 | ||||
-rw-r--r-- | src/arch/arm/isa/insts/branch.isa | 35 | ||||
-rw-r--r-- | src/arch/arm/isa/templates/branch.isa | 37 | ||||
-rw-r--r-- | src/arch/arm/predecoder.hh | 7 | ||||
-rw-r--r-- | src/arch/arm/types.hh | 13 |
5 files changed, 83 insertions, 10 deletions
diff --git a/src/arch/arm/insts/branch.hh b/src/arch/arm/insts/branch.hh index fbdd10d68..0e33a9214 100644 --- a/src/arch/arm/insts/branch.hh +++ b/src/arch/arm/insts/branch.hh @@ -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 diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa index d8ea2118e..84b9bb720 100644 --- a/src/arch/arm/isa/insts/branch.isa +++ b/src/arch/arm/isa/insts/branch.isa @@ -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) + \ diff --git a/src/arch/arm/isa/templates/branch.isa b/src/arch/arm/isa/templates/branch.isa index d1f581f51..6abf76963 100644 --- a/src/arch/arm/isa/templates/branch.isa +++ b/src/arch/arm/isa/templates/branch.isa @@ -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; + } +}}; + + diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh index 511bc29bc..08e1676c0 100644 --- a/src/arch/arm/predecoder.hh +++ b/src/arch/arm/predecoder.hh @@ -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; diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index e6865e280..b4ef07d8a 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -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); |