summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2011-03-17 19:20:20 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2011-03-17 19:20:20 -0500
commit5480ec798aba313a03c0760d88aeadff1037f48d (patch)
tree85728e51fa46ecc7b969cac5dd23fcd0b4f371e9
parent887e9e2b99deaddd669713f47da0642e6f6cb0c5 (diff)
downloadgem5-5480ec798aba313a03c0760d88aeadff1037f48d.tar.xz
ARM: Identify branches as conditional or unconditional and direct or indirect.
-rw-r--r--src/arch/arm/insts/branch.hh1
-rw-r--r--src/arch/arm/isa/insts/branch.isa35
-rw-r--r--src/arch/arm/isa/templates/branch.isa37
-rw-r--r--src/arch/arm/predecoder.hh7
-rw-r--r--src/arch/arm/types.hh13
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);