ARM: Identify branches as conditional or unconditional and direct or indirect.
This commit is contained in:
parent
887e9e2b99
commit
5480ec798a
5 changed files with 83 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -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) + \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue